diff options
| author | lachsinc <lachlansinclair@gmail.com> | 2018-10-05 16:49:48 +1000 |
|---|---|---|
| committer | lachsinc <lachlansinclair@gmail.com> | 2018-10-05 16:49:48 +1000 |
| commit | 992502f03b347b10db3bf45e31e93a02ba2f9b82 (patch) | |
| tree | ef9037791d6727f8e4d6d9bbd0d76b8e007faa40 /src | |
| parent | edc3a9392a35b7a3c90f6503617ccc2a1fb5a372 (diff) | |
Add debug info for proc ptrs.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ir.cpp | 125 | ||||
| -rw-r--r-- | src/ir_print.cpp | 9 |
2 files changed, 83 insertions, 51 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index edf3ad3ba..406a1c544 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -523,6 +523,7 @@ enum irDebugInfoKind { irDebugInfo_CompileUnit, irDebugInfo_File, irDebugInfo_Proc, + irDebugInfo_ProcType, irDebugInfo_Location, irDebugInfo_LexicalBlock, irDebugInfo_AllProcs, @@ -561,10 +562,13 @@ struct irDebugInfo { String name; irDebugInfo * file; TokenPos pos; - irDebugInfo * types; // !{return, return, param, param, param.. etc.} + irDebugInfo * type; // TODO(lachsinc): variables / retainedNodes ? } Proc; struct { + irDebugInfo * types; // !{return, return, param, param, param.. etc.} + } ProcType; + struct { TokenPos pos; irDebugInfo *scope; } Location; @@ -1968,10 +1972,76 @@ irDebugInfo *ir_add_debug_info_type_any(irModule *module) { } } +irDebugInfo *ir_add_debug_info_proc_type(irModule *module, Type *type) { + GB_ASSERT(type->kind == Type_Proc); + + irDebugInfo **existing = map_get(&module->debug_info, hash_type(type)); + if (existing != nullptr) { + GB_ASSERT((*existing)->kind == irDebugInfo_ProcType); + return *existing; + } + + irDebugInfo *di = ir_alloc_debug_info(irDebugInfo_ProcType); + map_set(&module->debug_info, hash_type(type), di); + + isize result_count = type->Proc.result_count; + isize param_count = type->Proc.param_count; + // gb_max(result_count, 1) because llvm expects explicit "null" return type + di->ProcType.types = ir_add_debug_info_array(module, 0, gb_max(result_count, 1) + param_count); + + // Result/return types + if (result_count >= 1) { + TypeTuple *results_tuple = &type->Proc.results->Tuple; + for_array(i, results_tuple->variables) { + Entity *e = results_tuple->variables[i]; + if (e->kind != Entity_Variable) { + continue; // TODO(lachsinc): Confirm correct? + } + + irDebugInfo *type_di = ir_add_debug_info_type(module, e->type, e, nullptr, nullptr); + GB_ASSERT_NOT_NULL(type_di); + array_add(&di->ProcType.types->DebugInfoArray.elements, type_di); + } + } else { + // llvm expects "!{null}" for a function without return type, use nullptr to represent it. + // TODO(lachsinc): Is there a specific "void" type we should refer to? + array_add(&di->ProcType.types->DebugInfoArray.elements, (irDebugInfo*)nullptr); + } + + // Param types + if (param_count >= 1) { + TypeTuple *params_tuple = &type->Proc.params->Tuple; + for_array(i, params_tuple->variables) { + Entity *e = params_tuple->variables[i]; + if (e->kind != Entity_Variable) { + continue; // TODO(lachsinc): Confirm correct? + } + + irDebugInfo *type_di = ir_add_debug_info_type(module, e->type, e, nullptr, nullptr); + GB_ASSERT_NOT_NULL(type_di); + array_add(&di->ProcType.types->DebugInfoArray.elements, type_di); + } + } + + return di; +} + irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irDebugInfo *scope, irDebugInfo *file) { - // if (!proc->module->generate_debug_info) { - // return nullptr; - // } + // NOTE(lachsinc): Special handling for procedure pointers - we hash their types directly into DISubroutineType's + // but we need them interpreted as pointers when we use them as variables. + if (type->kind == Type_Proc) { + if (e->kind == Entity_Variable || e->kind == Entity_TypeName) { + // TODO(lachsinc): Wasteful (maybe?). Create a derived type for _every_ different proc ptr type + irDebugInfo *di = ir_alloc_debug_info(irDebugInfo_DerivedType); + map_set(&module->debug_info, hash_pointer(di), di); + di->DerivedType.tag = irDebugBasicEncoding_pointer_type; + di->DerivedType.size = ir_debug_size_bits(t_rawptr); + di->DerivedType.base_type = ir_add_debug_info_proc_type(module, type); + return di; + } else { + GB_PANIC("Proc definitions should have their type created manually (not through this function)"); + } + } irDebugInfo **existing = map_get(&module->debug_info, hash_type(type)); if (existing != nullptr) { @@ -2258,10 +2328,6 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD return ir_add_debug_info_type_bit_set(module, type, e, scope); } - if (is_type_tuple(type)) { - int i = 0; - } - // // TODO(lachsinc): HACK For now any remaining types interpreted as a rawptr. // @@ -2396,53 +2462,14 @@ irDebugInfo *ir_add_debug_info_proc(irProcedure *proc) { irDebugInfo *scope = file; // TODO(lachsinc): Should scope be made separate to file? irDebugInfo *di = ir_alloc_debug_info(irDebugInfo_Proc); + map_set(&proc->module->debug_info, hash_entity(entity), di); di->Proc.entity = entity; di->Proc.name = proc->name; di->Proc.file = file; di->Proc.pos = entity->token.pos; - - isize result_count = proc->type->Proc.result_count; - isize param_count = proc->type->Proc.param_count; - // gb_max(result_count, 1) because llvm expects explicit "null" return type - di->Proc.types = ir_add_debug_info_array(proc->module, 0, gb_max(result_count, 1) + param_count); - - // Result/return types - if (result_count >= 1) { - TypeTuple *results_tuple = &proc->type->Proc.results->Tuple; - for_array(i, results_tuple->variables) { - Entity *e = results_tuple->variables[i]; - if (e->kind != Entity_Variable) { - continue; // TODO(lachsinc): Confirm correct? - } - - irDebugInfo *type_di = ir_add_debug_info_type(proc->module, e->type, e, nullptr, nullptr); - GB_ASSERT_NOT_NULL(type_di); - array_add(&di->Proc.types->DebugInfoArray.elements, type_di); - } - } else { - // llvm expects "!{null}" for a function without return type, use nullptr to represent it. - // TODO(lachsinc): Is there a specific "void" type we should refer to? - array_add(&di->Proc.types->DebugInfoArray.elements, (irDebugInfo*)nullptr); - } - - // Param types - if (param_count >= 1) { - TypeTuple *params_tuple = &proc->type->Proc.params->Tuple; - for_array(i, params_tuple->variables) { - Entity *e = params_tuple->variables[i]; - if (e->kind != Entity_Variable) { - continue; // TODO(lachsinc): Confirm correct? - } - - irDebugInfo *type_di = ir_add_debug_info_type(proc->module, e->type, e, nullptr, nullptr); - GB_ASSERT_NOT_NULL(type_di); - array_add(&di->Proc.types->DebugInfoArray.elements, type_di); - } - } + di->Proc.type = ir_add_debug_info_proc_type(proc->module, proc->type); proc->debug_scope = di; - - map_set(&proc->module->debug_info, hash_entity(entity), di); return di; } diff --git a/src/ir_print.cpp b/src/ir_print.cpp index e880f8c9c..ef7e701da 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1964,6 +1964,7 @@ void print_llvm_ir(irGen *ir) { break; case irDebugInfo_Proc: // TODO(lachsinc): We need to store scope info inside di, not just file info, for procs. + // Should all subprograms have distinct ?? ir_fprintf(f, "distinct !DISubprogram(" "name: \"%.*s\"" ", linkageName: \"%.*s\"" @@ -1976,7 +1977,7 @@ void print_llvm_ir(irGen *ir) { ", flags: DIFlagPrototyped" ", isOptimized: false" ", unit: !%d" - ", type: !DISubroutineType(types: !%d)", + ", type: !%d", LIT(di->Proc.entity->token.string), LIT(di->Proc.name), di->Proc.file->id, // TODO(lachsinc): HACK For now lets pretend all procs scope's == file. @@ -1984,9 +1985,13 @@ void print_llvm_ir(irGen *ir) { di->Proc.pos.line, di->Proc.pos.line, // NOTE(lachsinc): Assume scopeLine always same as line. m->debug_compile_unit->id, - di->Proc.types->id); + di->Proc.type->id); ir_write_byte(f, ')'); // !DISubprogram( break; + case irDebugInfo_ProcType: + ir_fprintf(f, "!DISubroutineType(types: !%d)", + di->ProcType.types->id); + break; case irDebugInfo_Location: GB_ASSERT_NOT_NULL(di->Location.scope); ir_fprintf(f, "!DILocation(" |