diff --git a/src/dwarf/dwarf_writer.h b/src/dwarf/dwarf_writer.h index 880f3f92..821c98fd 100644 --- a/src/dwarf/dwarf_writer.h +++ b/src/dwarf/dwarf_writer.h @@ -196,11 +196,14 @@ internal DW_WriterAttrib * dw_writer_push_attrib_uint (DW_Writer *writer, internal DW_WriterAttrib * dw_writer_push_attrib_enum (DW_Writer *writer, DW_AttribKind kind, S64 e ); internal DW_WriterAttrib * dw_writer_push_attrib_ref (DW_Writer *writer, DW_AttribKind kind, DW_WriterTag *ref ); internal DW_WriterAttrib * dw_writer_push_attrib_exprloc (DW_Writer *writer, DW_AttribKind kind, String8 exprloc ); +internal DW_WriterAttrib * dw_writer_push_attrib_expression (DW_Writer *writer, DW_AttribKind kind, DW_ExprEnc *encs, U64 encs_count); internal DW_WriterAttrib * dw_writer_push_attrib_line_ptr (DW_Writer *writer, DW_AttribKind kind, void * line_ptr ); internal DW_WriterAttrib * dw_writer_push_attrib_mac_ptr (DW_Writer *writer, DW_AttribKind kind, void * mac_ptr ); internal DW_WriterAttrib * dw_writer_push_attrib_rng_list_ptr(DW_Writer *writer, DW_AttribKind kind, void * rng_list_ptr); internal DW_WriterAttrib * dw_writer_push_attrib_implicit (DW_Writer *writer, DW_AttribKind kind, S64 implicit ); +#define dw_writer_push_attrib_expressionv(w, k, ...) dw_writer_push_attrib_expression(w, k, (DW_ExprEnc[]){ __VA_ARGS__ }, ArrayCount(((DW_ExprEnc[]){ __VA_ARGS__ })) ) + internal void dw_writer_emit(DW_Writer *writer); #ifdef OBJ_H internal void dw_writer_emit_to_obj(DW_Writer *writer, OBJ *obj); diff --git a/src/rdi_from_dwarf/rdi_from_dwarf.c b/src/rdi_from_dwarf/rdi_from_dwarf.c index 15e129aa..15ded770 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf.c +++ b/src/rdi_from_dwarf/rdi_from_dwarf.c @@ -1566,7 +1566,7 @@ d2r_is_type_tag_converted(DW_TagNode *tag_node) } internal RDIM_Type * -d2r_find_or_convert_type(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, DW_Tag tag, DW_AttribKind kind) +d2r_find_or_convert_type(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, Arch arch, DW_Tag tag, DW_AttribKind kind) { RDIM_Type *type = type_table->builtin_types[RDI_TypeKind_Void]; @@ -1589,7 +1589,7 @@ d2r_find_or_convert_type(Arena *arena, D2R_TypeTable *type_table, DW_Input *inpu if (type == 0) { // issue type conversion DW_TagNode *ref_node = dw_tag_node_from_info_off(cu, ref.info_off); - d2r_convert_types(arena, type_table, input, cu, cu_lang, ref_node); + d2r_convert_types(arena, type_table, input, cu, cu_lang, arch, ref_node); // if we do not have a converted type at this point then debug info is malformed type = d2r_type_from_offset(type_table, ref.info_off); @@ -1614,6 +1614,7 @@ d2r_convert_types(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, + Arch arch, DW_TagNode *root) { Temp scratch = scratch_begin(&arena, 1); @@ -1639,7 +1640,7 @@ d2r_convert_types(Arena *arena, Assert(!tag_node->first_child); d2r_tag_iterator_skip_children(it); } else { - RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, tag, DW_AttribKind_Type); + RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_Class; @@ -1697,7 +1698,7 @@ d2r_convert_types(Arena *arena, log_user_errorf("childless enum @ .debug_info+%llx", tag.info_off); } } else { - RDIM_Type *enum_base_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, tag, DW_AttribKind_Type); + RDIM_Type *enum_base_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_Enum; @@ -1706,7 +1707,7 @@ d2r_convert_types(Arena *arena, } } break; case DW_TagKind_SubroutineType: { - RDIM_Type *ret_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, tag, DW_AttribKind_Type); + RDIM_Type *ret_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch, tag, DW_AttribKind_Type); // collect parameters RDIM_TypeList param_list = {0}; @@ -1732,7 +1733,7 @@ d2r_convert_types(Arena *arena, d2r_tag_iterator_skip_children(it); } break; case DW_TagKind_Typedef: { - RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, tag, DW_AttribKind_Type); + RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_Alias; type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); @@ -1757,25 +1758,43 @@ d2r_convert_types(Arena *arena, case DW_ATE_Boolean: kind = RDI_TypeKind_Bool; break; case DW_ATE_ComplexFloat: { switch (byte_size) { - case 4: kind = RDI_TypeKind_ComplexF32; break; - case 8: kind = RDI_TypeKind_ComplexF64; break; - case 10: kind = RDI_TypeKind_ComplexF80; break; - case 16: kind = RDI_TypeKind_ComplexF128; break; + case 8: kind = RDI_TypeKind_ComplexF32; break; + case 16: kind = RDI_TypeKind_ComplexF64; break; + case 24: kind = RDI_TypeKind_ComplexF80; break; + case 32: kind = RDI_TypeKind_ComplexF128; break; default: log_user_errorf("unexpected size"); break; } } break; case DW_ATE_Float: { + String8 name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + if (arch == Arch_x64 || arch == Arch_arm64) { + if (str8_match(name, str8_lit("__float80"), 0)) { + kind = RDI_TypeKind_F80; + } else if (str8_match(name, str8_lit("__float128"), 0)) { + kind = RDI_TypeKind_F128; + } else if (str8_match(name, str8_lit("_Float16"), 0)) { + kind = RDI_TypeKind_F16; + } else if (str8_match(name, str8_lit("__bf16"), 0)) { + NotImplemented; + } + if (kind != RDI_TypeKind_NULL) { break; } + } + switch (byte_size) { D2R_ValueType_Float_XList - default: log_user_errorf("unexpected size"); break; + default: log_user_errorf("unexpected size"); break; } } break; case DW_ATE_Signed: { + String8 name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); + if (str8_match(name, str8_lit("wchar_t"), 0)) { goto do_signed_char; } + switch (byte_size) { D2R_ValueType_Signed_XList default: log_user_errorf("unexpected size"); break; } } break; + do_signed_char:; case DW_ATE_SignedChar: { switch (byte_size) { case 1: kind = RDI_TypeKind_Char8; break; @@ -1790,6 +1809,7 @@ d2r_convert_types(Arena *arena, default: log_user_errorf("unexpected size"); break; } } break; + case DW_ATE_Utf: case DW_ATE_UnsignedChar: { switch (byte_size) { case 1: kind = RDI_TypeKind_UChar8; break; @@ -1819,9 +1839,6 @@ d2r_convert_types(Arena *arena, case DW_ATE_DecimalFloat: { NotImplemented; } break; - case DW_ATE_Utf: { - NotImplemented; - } break; case DW_ATE_Ucs: { NotImplemented; } break; @@ -1839,7 +1856,7 @@ d2r_convert_types(Arena *arena, type->byte_size = byte_size; } break; case DW_TagKind_PointerType: { - RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, tag, DW_AttribKind_Type); + RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch, tag, DW_AttribKind_Type); // TODO: if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Allocated)) { @@ -1877,7 +1894,7 @@ d2r_convert_types(Arena *arena, log_infof("TODO: handle name attrib @ .debug_info+%llx", tag.info_off); } - RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, tag, DW_AttribKind_Type); + RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_Modifier; type->byte_size = cu->address_size; @@ -1889,7 +1906,7 @@ d2r_convert_types(Arena *arena, log_infof("TODO: handle name attrib @ .debug_info+%llx", tag.info_off); } - RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, tag, DW_AttribKind_Type); + RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_Modifier; type->byte_size = cu->address_size; @@ -1904,7 +1921,7 @@ d2r_convert_types(Arena *arena, log_infof("TODO: handle alignment attrib @ .debug_info+%llx", tag.info_off); } - RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, tag, DW_AttribKind_Type); + RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_Modifier; type->byte_size = cu->address_size; @@ -1980,7 +1997,7 @@ d2r_convert_types(Arena *arena, SLLStackPush(subrange_stack, s); } - RDIM_Type *array_base_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, tag, DW_AttribKind_Type); + RDIM_Type *array_base_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch, tag, DW_AttribKind_Type); RDIM_Type *direct_type = array_base_type; U64 size_cursor = array_base_type->byte_size; for EachNode(s, struct SubrangeNode, subrange_stack) { @@ -2016,7 +2033,7 @@ d2r_convert_types(Arena *arena, DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); if (parent_tag.kind == DW_TagKind_StructureType || parent_tag.kind == DW_TagKind_ClassType) { RDIM_Type *parent = d2r_type_from_offset(type_table, parent_tag.info_off); - RDIM_Type *type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, tag, DW_AttribKind_Type); + RDIM_Type *type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch, tag, DW_AttribKind_Type); RDIM_UDTMember *member = rdim_udt_push_member(arena, &g_d2r_shared.udts, parent->udt); member->kind = RDI_MemberKind_Base; member->type = type; @@ -2965,6 +2982,11 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) type->byte_size = rdi_size_from_basic_type_kind(type_kind); builtin_types[type_kind] = type; } + + // fixup float80 size + if (arch == Arch_x64 || arch == Arch_arm64) { + builtin_types[RDI_TypeKind_F80]->byte_size = 16; + } builtin_types[RDI_TypeKind_Void]->byte_size = rdi_addr_size_from_arch(g_d2r_shared.top_level_info.arch); builtin_types[RDI_TypeKind_Handle]->byte_size = rdi_addr_size_from_arch(g_d2r_shared.top_level_info.arch); @@ -3011,7 +3033,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) type_table->builtin_types = builtin_types; // convert debug info - d2r_convert_types(arena, type_table, &input, cu, cu_lang, tag_tree.root); + d2r_convert_types(arena, type_table, &input, cu, cu_lang, arch, tag_tree.root); d2r_convert_udts(arena, type_table, &input, cu, cu_lang, tag_tree.root); d2r_convert_symbols(arena, type_table, global_scope, &input, cu, cu_lang, image_base, arch, tag_tree.root); diff --git a/src/rdi_from_dwarf/rdi_from_dwarf.h b/src/rdi_from_dwarf/rdi_from_dwarf.h index 543dbd8d..e715cc3d 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf.h +++ b/src/rdi_from_dwarf/rdi_from_dwarf.h @@ -241,8 +241,8 @@ internal DW_Tag d2r_tag_iterator_parent_tag (D2R_TagIterator *ite internal void d2r_flag_converted_tag(DW_TagNode *tag_node); internal B8 d2r_is_tag_converted (DW_TagNode *tag_node); -internal RDIM_Type * d2r_find_or_convert_type(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, DW_Tag tag, DW_AttribKind kind); -internal void d2r_convert_types(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, DW_TagNode *root); +internal RDIM_Type * d2r_find_or_convert_type(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, Arch arch, DW_Tag tag, DW_AttribKind kind); +internal void d2r_convert_types(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, Arch arch, DW_TagNode *root); //////////////////////////////// //~ UDT Conversion diff --git a/src/torture/torture_d2r.c b/src/torture/torture_d2r.c index f4648a62..2b837911 100644 --- a/src/torture/torture_d2r.c +++ b/src/torture/torture_d2r.c @@ -25,10 +25,13 @@ d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer) String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); Assert(exe.size > 0); + B32 was_pdb_deleted = os_delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb"))); + Assert(was_pdb_deleted); + t_invoke(str8_lit("radbin.exe"), str8_lit("-rdi a.exe"), max_U64); Assert(g_last_exit_code == 0); - String8 raw_rdi = t_read_file(scratch.arena, str8_lit("a.rdi")); + String8 raw_rdi = t_read_file(arena, str8_lit("a.rdi")); Assert(raw_rdi.size > 0); RDI_Parsed *rdi = push_array(arena, RDI_Parsed, 1); @@ -39,36 +42,221 @@ d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer) return rdi; } +internal RDI_TypeNode * +d2rt_type_from_name(RDI_Parsed *rdi, RDI_ParsedNameMap *map, char *name) +{ + String8 s = str8_cstring(name); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, map, s.str, s.size); + + U32 id_count = 0; + U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + + if (id_count == 1) { + return rdi_element_from_name_idx(rdi, TypeNodes, ids[0]); + } + return 0; +} + +T_BeginTest(d2r_types) +{ + DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64); + { + dw_writer_tag_begin(writer, DW_TagKind_CompileUnit); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Producer, "Test"); + +#define DeclBaseType(tt, n, e, s) \ + DW_WriterTag *tt = dw_writer_tag_begin(writer, DW_TagKind_BaseType); \ + dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, s); \ + dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_##e); \ + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, n); \ + dw_writer_tag_end(writer); + DeclBaseType(char_type, "char", SignedChar, 1); + DeclBaseType(unsigned_char_type, "unsigned char", UnsignedChar, 1); + DeclBaseType(char8_type, "char8_t", Utf, 1); + DeclBaseType(char16_type, "char16_t", Utf, 2); + DeclBaseType(char32_type, "char32_t", Utf, 4); + DeclBaseType(wchar_type, "wchar_t", Signed, 4); + DeclBaseType(bool_type, "_Bool", Boolean, 1); + DeclBaseType(short_type, "short", Signed, 2); + DeclBaseType(unsigned_short_type, "unsigned short", Unsigned, 2); + DeclBaseType(short_unsigned_int_type, "short unsigned int", Unsigned, 2); + DeclBaseType(short_int_type, "short int", Signed, 2); + DeclBaseType(unsigned_int_type, "unsigned int", Unsigned, 4); + DeclBaseType(int_type, "int", Signed, 4); + DeclBaseType(long_int_type, "long int", Signed, 8); + DeclBaseType(long_unsigned_int_type, "long unsigned int", Unsigned, 8); + DeclBaseType(long_long_int_type, "long long int", Signed, 8); + DeclBaseType(long_long_unsigned_int, "long long unsigned int", Unsigned, 8); + DeclBaseType(float_type, "float", Float, 4); + DeclBaseType(double_type, "double", Float, 8); + DeclBaseType(long_double_type, "long double", Float, 16); + DeclBaseType(float16_type, "_Float16", Float, 2); + DeclBaseType(float80_type, "__float80", Float, 16); + DeclBaseType(float128_type, "_float128", Float, 16); + DeclBaseType(complex_float, "complex float", ComplexFloat, 8); + DeclBaseType(complex_doulbe, "complex double", ComplexFloat, 16); + DeclBaseType(complex_long_double, "complex long double", ComplexFloat, 32); + //DeclBaseType("__bf16", Float, 2); +#undef DeclBaseType + +#define DeclStdint(n, a) \ + do { \ + dw_writer_tag_begin(writer, DW_TagKind_Typedef); \ + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, n); \ + dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, a); \ + dw_writer_tag_end(writer); \ + } while (0) + DeclStdint("uint8_t", unsigned_char_type); + DeclStdint("uint16_t", unsigned_short_type); + DeclStdint("uint32_t", unsigned_int_type); + DeclStdint("uint64_t", long_unsigned_int_type); + DeclStdint("int8_t", char_type); + DeclStdint("int16_t", short_type); + DeclStdint("int32_t", int_type); + DeclStdint("int64_t", long_int_type); +#undef DeclStdInt + + dw_writer_tag_end(writer); + } + + RDI_Parsed *rdi = d2r_rdi_from_dwarf_writer(scratch.arena, writer); + RDI_NameMap *types_nm = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Types); + T_Ok(types_nm); + + RDI_ParsedNameMap types_map = {0}; + rdi_parsed_from_name_map(rdi, types_nm, &types_map); + +#define TestBuiltinType(n, bs, r) \ + do { \ + RDI_TypeNode *alias = d2rt_type_from_name(rdi, &types_map, n); \ + T_Ok(alias); \ + T_Ok(alias->kind == RDI_TypeKind_Alias); \ + T_Ok(alias->flags == 0); \ + T_Ok(alias->byte_size == bs); \ + RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, alias->user_defined.direct_type_idx); \ + T_Ok(type); \ + T_Ok(type->kind == RDI_TypeKind_##r); \ + T_Ok(type->flags == 0); \ + T_Ok(type->byte_size == alias->byte_size); \ + T_Ok(str8_match(str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx), str8_lit(Stringify(r)), 0)); \ + } while (0) + TestBuiltinType("char", 1, Char8); + TestBuiltinType("char8_t", 1, UChar8); + TestBuiltinType("char16_t", 2, UChar16); + TestBuiltinType("char32_t", 4, UChar32); + TestBuiltinType("unsigned char", 1, UChar8); + TestBuiltinType("wchar_t", 4, Char32); + TestBuiltinType("_Bool", 1, Bool); + TestBuiltinType("short", 2, S16); + TestBuiltinType("unsigned short", 2, U16); + TestBuiltinType("short unsigned int", 2, U16); + TestBuiltinType("short int", 2, S16); + TestBuiltinType("unsigned int", 4, U32); + TestBuiltinType("int", 4, S32); + TestBuiltinType("long int", 8, S64); + TestBuiltinType("long unsigned int", 8, U64); + TestBuiltinType("long long int", 8, S64); + TestBuiltinType("float", 4, F32); + TestBuiltinType("double", 8, F64); + TestBuiltinType("long double", 16, F128); + TestBuiltinType("_Float16", 2, F16); + TestBuiltinType("__float80", 16, F80); + TestBuiltinType("_float128", 16, F128); + TestBuiltinType("complex float", 8, ComplexF32); + TestBuiltinType("complex double", 16, ComplexF64); + TestBuiltinType("complex long double", 32, ComplexF128); + // TODO: bfloat16 + //TestBuiltinType("__bf16", 2, BF16); +#undef TestBuiltinType + +#define TestStdint(n, s, t) \ + do { \ + RDI_TypeNode *td = d2rt_type_from_name(rdi, &types_map, n); \ + T_Ok(td); \ + T_Ok(td->kind == RDI_TypeKind_Alias); \ + T_Ok(td->flags == 0); \ + T_Ok(td->byte_size == s); \ + RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, td->user_defined.direct_type_idx); \ + T_Ok(type); \ + T_Ok(type->kind == RDI_TypeKind_Alias); \ + T_Ok(type->flags == 0); \ + T_Ok(type->byte_size = td->byte_size); \ + T_Ok(str8_match(str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx), str8_lit(t), 0)); \ + } while (0) + TestStdint("uint8_t", 1, "unsigned char"); + TestStdint("uint16_t", 2, "unsigned short"); + TestStdint("uint32_t", 4, "unsigned int"); + TestStdint("uint64_t", 8, "long unsigned int"); + TestStdint("int8_t", 1, "char"); + TestStdint("int16_t", 2, "short"); + TestStdint("int32_t", 4, "int"); + TestStdint("int64_t", 8, "long int"); +#undef TestStdint + + dw_writer_end(&writer); +} +T_EndTest; + T_BeginTest(d2r_general) { DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64); - dw_writer_tag_begin(writer, DW_TagKind_CompileUnit); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Producer, "Test"); - // declare char type - DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType); - dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 1); - dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_SignedChar); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "char"); - dw_writer_tag_end(writer); - // declare function - dw_writer_tag_begin(writer, DW_TagKind_SubProgram); - dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, 0x140173f9); - dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, 0x14017474b); - dw_writer_push_attrib_flag(writer, DW_AttribKind_External, 1); - dw_writer_push_attrib_flag(writer, DW_AttribKind_Prototyped, 1); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "FooBar"); - // declare variable - dw_writer_tag_begin(writer, DW_TagKind_Variable); - dw_writer_push_attrib_expression(writer, DW_AttribKind_Location, &(DW_ExprEnc)DW_ExprEnc_Op(Reg7), 1); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "TestLocal"); - dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type); + { + dw_writer_tag_begin(writer, DW_TagKind_CompileUnit); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Producer, "Test"); + // declare char type + DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType); + dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 1); + dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_SignedChar); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "char"); dw_writer_tag_end(writer); - dw_writer_tag_end(writer); + // declare function + dw_writer_tag_begin(writer, DW_TagKind_SubProgram); + dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, 0x140173f9); + dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, 0x14017474b); + dw_writer_push_attrib_flag(writer, DW_AttribKind_External, 1); + dw_writer_push_attrib_flag(writer, DW_AttribKind_Prototyped, 1); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "FooBar"); + // declare variable + dw_writer_tag_begin(writer, DW_TagKind_Variable); + dw_writer_push_attrib_expressionv(writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg7)); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "TestLocal"); + dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type); + dw_writer_tag_end(writer); + dw_writer_tag_end(writer); + } RDI_Parsed *rdi = d2r_rdi_from_dwarf_writer(scratch.arena, writer); - RDI_Procedure *proc_name = rdi_procedure_from_name_cstr(rdi, "FooBar"); - T_Ok(proc_name); + RDI_Procedure *proc = rdi_procedure_from_name_cstr(rdi, "FooBar"); + T_Ok(proc); + T_Ok(proc->link_flags == RDI_LinkFlag_External); + String8 proc_name = str8_from_rdi_string_idx(rdi, proc->name_string_idx); + T_Ok(str8_match(proc_name, str8_lit("FooBar"), 0)); + + RDI_Scope *root_scope = rdi_root_scope_from_procedure(rdi, proc); + T_Ok(root_scope); + T_Ok(root_scope->local_count == 1); + + RDI_Local *test_local = rdi_element_from_name_idx(rdi, Locals, root_scope->local_first + 0); + T_Ok(test_local); + T_Ok(test_local->kind == RDI_LocalKind_Variable); + String8 test_local_name = str8_from_rdi_string_idx(rdi, test_local->name_string_idx); + T_Ok(str8_match(test_local_name, str8_lit("TestLocal"), 0)); + + RDI_TypeNode *test_local_type = rdi_element_from_name_idx(rdi, TypeNodes, test_local->type_idx); + T_Ok(test_local_type); + T_Ok(test_local_type->kind == RDI_TypeKind_Alias); + T_Ok(test_local_type->flags == 0); + String8 alias_name = str8_from_rdi_string_idx(rdi, test_local_type->user_defined.name_string_idx); + T_Ok(str8_match(alias_name, str8_lit("char"), 0)); + + RDI_TypeNode *char_type = rdi_element_from_name_idx(rdi, TypeNodes, test_local_type->user_defined.direct_type_idx); + T_Ok(char_type); + T_Ok(char_type->kind == RDI_TypeKind_Char8); + T_Ok(char_type->flags == 0); + T_Ok(char_type->byte_size == 1); + String8 char_type_name = str8_from_rdi_string_idx(rdi, char_type->built_in.name_string_idx); + T_Ok(str8_match(char_type_name, str8_lit("Char8"), 0)); dw_writer_end(&writer); }