diff options
| author | lachsinc <lachlansinclair@gmail.com> | 2018-09-27 21:50:57 +1000 |
|---|---|---|
| committer | lachsinc <lachlansinclair@gmail.com> | 2018-09-27 21:50:57 +1000 |
| commit | 9e73189d636b7723302553f48dddf93cea8f073f (patch) | |
| tree | b8e2b37d40c365b21372667dc4b659716d11c2e5 /src/ir.cpp | |
| parent | 11bddf270c9f96c01768fe3e0d6c64c372300dd0 (diff) | |
Tagged union debug info. Aggregate type fixes (unions inside structs etc.).
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 119 |
1 files changed, 77 insertions, 42 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 7f494d363..7219bead2 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1666,32 +1666,53 @@ irDebugInfo *ir_add_debug_info_field_internal(irModule *module, String name, Typ return di; } -// TODO(lachsinc): Cleanup params. -irDebugInfo *ir_add_debug_info_field(irModule *module, irDebugInfo *scope, Entity *e, Type *struct_type, i32 index, Type *type, irDebugInfo *file) { - GB_ASSERT_NOT_NULL(e); - - Type *named = type; - type = base_type(type); - GB_ASSERT(type->kind != Type_Named); - - irDebugInfo **existing = map_get(&module->debug_info, hash_entity(e)); - if (existing != nullptr) { - return *existing; - } - - i32 offset = 0; - if (struct_type && struct_type->Struct.are_offsets_set) { - offset = ir_debug_info_bits(struct_type->Struct.offsets[index]); - } else { - offset = ir_debug_info_bits(type_offset_of(type, index)); +// TODO(lachsinc): Cleanup params, either scope or scope_type, not both. +// Pass name, file, pos in manually? Would be much cleaner. +irDebugInfo *ir_add_debug_info_field(irModule *module, irDebugInfo *scope, Entity *e, Type *scope_type, i32 index, Type *type, irDebugInfo *file) { + // NOTE(lachsinc): This lookup will only work for struct fields!! + // TODO(lachsinc): Do we even need to do this? + if (e) { + irDebugInfo **existing = map_get(&module->debug_info, hash_entity(e)); + if (existing != nullptr) { + return *existing; + } + } + + // TODO(lachsinc): Cleanup + irDebugInfo *di = ir_add_debug_info_field_internal(module, make_string(nullptr, 0), type, 0, scope); + void *ptr_to_hash = nullptr; + if (scope_type) { + Type *scope_base = base_type(scope_type); + if (is_type_struct(scope_type)) { + if (scope_base->Struct.are_offsets_set) { + di->DerivedType.offset = ir_debug_info_bits(scope_base->Struct.offsets[index]); + } else { + di->DerivedType.offset = ir_debug_info_bits(type_offset_of(scope_base, index)); + } + if (e) { + ptr_to_hash = e; + di->DerivedType.name = e->token.string; + di->DerivedType.pos = e->token.pos; + } else { + GB_PANIC("Unreachable"); // struct field Entity's should be provided. + } + } else if (is_type_union(scope_base)) { + // TODO(lachsinc): Handle this in a more generic manner/pass in??... + // Token token = base_type(scope_base)->Union.node->UnionType.token; + // di->DerivedType.name = token.string; + // di->DerivedType.pos = token.pos; + if (is_type_named(type)) { + di->DerivedType.name = type->kind == Type_Named ? type->Named.name : type->Basic.name; + } + ptr_to_hash = di; // TODO(lachsinc): Correct ?? I don't think unions have individual entities for their fields?? idk. + } } - irDebugInfo *di = ir_add_debug_info_field_internal(module, e->token.string, type, offset, scope); - map_set(&module->debug_info, hash_entity(e), di); - // di->DerivedType.align = ir_debug_align_bits(type); di->DerivedType.file = file; - di->DerivedType.pos = e->token.pos; - // di->DerivedType.base_type = ir_add_debug_info_type(module, type, e, scope, file); + // di->DerivedType.align = ir_debug_align_bits(type); + + GB_ASSERT_NOT_NULL(ptr_to_hash); + map_set(&module->debug_info, hash_pointer(ptr_to_hash), di); return di; } @@ -1869,13 +1890,16 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD } } - // NOTE(lachsinc): Types are inserted into debug_info map as their named, not base_type()'d, counterpart. + // NOTE(lachsinc): Types should be inserted into debug_info map as their named, not base_type()'d, counterpart. Type *base = base_type(type); if (type->kind == Type_Named) { Type *named_base = type->Named.base; // TODO(lachsinc): Better way to determine distinct etc. or just handle structs, enums before we reach here. - if (named_base->kind != Type_Struct && named_base->kind != Type_Enum) { + // ir_is_type_aggregate() except with no call to base_type(). + if (named_base->kind != Type_Struct && + named_base->kind != Type_Union && + named_base->kind != Type_Enum) { // distinct / typedef etc. irDebugInfo *di = ir_alloc_debug_info(irDebugInfo_DerivedType); if (type->kind == Type_Named) { @@ -1947,24 +1971,28 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD return di; } - if (is_type_struct(type) || is_type_enum(type)) { // || is_type_union(type) TODO(lachsinc): + if (is_type_struct(type) || is_type_union(type) || is_type_enum(type)) { + if (type->kind == Type_Named) { + // Named named's should be handled prior as typedefs. + GB_ASSERT(type->Named.base->kind != Type_Named); + } + irDebugInfo *di = ir_alloc_debug_info(irDebugInfo_CompositeType); + // NOTE(lachsinc): Set map value before resolving field types to avoid circular dependencies. + map_set(&module->debug_info, hash_type(type), di); + if (is_type_named(type)) { + di->CompositeType.name = type->kind == Type_Named ? type->Named.name : type->Basic.name; + } if (e) { di->CompositeType.file = file; di->CompositeType.scope = scope; di->CompositeType.pos = e->token.pos; } di->CompositeType.size = ir_debug_size_bits(type); - di->CompositeType.align = ir_debug_align_bits(type); - di->CompositeType.base_type = nullptr; - - // NOTE(lachsinc): Set map value before resolving field types to avoid circular dependencies. - map_set(&module->debug_info, hash_type(type), di); + di->CompositeType.align = ir_debug_align_bits(type); // TODO(lachsinc): Necessary? if (is_type_struct(type)) { - if (is_type_named(type)) { - di->CompositeType.name = type->kind == Type_Named ? type->Named.name : type->Basic.name; - } + GB_ASSERT(base->kind == Type_Struct); di->CompositeType.elements = ir_add_debug_info_array(module, 0, base->Struct.fields.count); for_array(field_index, base->Struct.fields) { array_add(&di->CompositeType.elements->DebugInfoArray.elements, @@ -1973,15 +2001,22 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD } di->CompositeType.tag = irDebugBasicEncoding_structure_type; } else if (is_type_union(type)) { - di->CompositeType.name = str_lit("union_name_todo"); - di->CompositeType.elements = nullptr; // ir_add_debug_info_array(module, 0, 0); - // TODO(lachsinc): Add elements for union + GB_ASSERT(base->kind == Type_Union); di->CompositeType.tag = irDebugBasicEncoding_union_type; - } else if (is_type_enum(type)) { - if (type->kind == Type_Named) { - di->CompositeType.name = type->Named.name; + di->CompositeType.elements = ir_add_debug_info_array(module, 0, base->Union.variants.count); + // TODO(lachsinc): Cleanup; this should be handled in a more generic manner for all types. + file = ir_add_debug_info_file(module, base->Union.node->file); + GB_ASSERT_NOT_NULL(file); // Union debug info requires file info + di->CompositeType.file = file; + di->CompositeType.pos = base->Union.node->UnionType.token.pos; + for_array(field_index, base->Union.variants) { + array_add(&di->CompositeType.elements->DebugInfoArray.elements, + ir_add_debug_info_field(module, di, nullptr, type, cast(i32)field_index, + base->Union.variants[field_index], file)); } - di->CompositeType.base_type = ir_add_debug_info_type(module, type->Named.base->Enum.base_type, e, scope, file); + } else if (is_type_enum(type)) { + GB_ASSERT(base->kind == Type_Enum); + di->CompositeType.base_type = ir_add_debug_info_type(module, base->Enum.base_type, e, scope, file); di->CompositeType.elements = ir_add_debug_info_array(module, 0, base->Enum.fields.count); for_array(field_index, base->Enum.fields) { array_add(&di->CompositeType.elements->DebugInfoArray.elements, @@ -2061,7 +2096,7 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD // TODO(lachsinc): Looks like "generated_struct_type" map.entries.data is just a u8*, we could // always look at the map header and create the debug info manually (if we // want struct members to be interpreted as the correct type). - // Also; are hashes meant to be interpreted as bool*'s ?? + // Also; are hashes meant to be interpreted as bool*'s ?? or is that simply slot occupied data? return ir_add_debug_info_type(module, type->Map.generated_struct_type, e, scope, file); } |