@@ -1756,15 +1756,15 @@ d2r_tag_iterator_parent_tag(D2R_TagIterator *iter)
17561756}
17571757
17581758internal void
1759- d2r_flag_converted_tag (DW_TagNode * tag_node )
1759+ d2r_flag_converted_type_tag (DW_TagNode * tag_node )
17601760{
1761- tag_node -> tag .v [ 0 ] = 1 ;
1761+ tag_node -> tag .v |= D2R_TagFlags_TypeConverted ;
17621762}
17631763
17641764internal B8
1765- d2r_is_tag_converted (DW_TagNode * tag_node )
1765+ d2r_is_type_tag_converted (DW_TagNode * tag_node )
17661766{
1767- return tag_node -> tag .v [ 0 ] ;
1767+ return !!( tag_node -> tag .v & D2R_TagFlags_TypeConverted ) ;
17681768}
17691769
17701770internal RDIM_Type *
@@ -1825,12 +1825,12 @@ d2r_convert_types(Arena *arena,
18251825 DW_Tag tag = tag_node -> tag ;
18261826
18271827 // skip converted tags
1828- if (d2r_is_tag_converted (tag_node )) {
1828+ if (d2r_is_type_tag_converted (tag_node )) {
18291829 d2r_tag_iterator_skip_children (it );
18301830 continue ;
18311831 }
18321832 // mark the tag as converted here, because during conversion we may recurse on the same tag
1833- d2r_flag_converted_tag (tag_node );
1833+ d2r_flag_converted_type_tag (tag_node );
18341834
18351835 switch (tag .kind ) {
18361836 case DW_TagKind_ClassType : {
@@ -2196,20 +2196,44 @@ d2r_convert_types(Arena *arena,
21962196 }
21972197
21982198 RDIM_Type * parent = d2r_type_from_offset (type_table , parent_tag .info_off );
2199- if (parent -> udt != 0 )
2200- {
2201- RDIM_Type * type = d2r_find_or_convert_type (arena , type_table , input , cu , cu_lang , arch_addr_size , tag , DW_AttribKind_Type );
2202- RDIM_UDTMember * member = rdim_udt_push_member (arena , & udts , parent -> udt );
2203- member -> kind = RDI_MemberKind_Base ;
2204- member -> type = type ;
2205- member -> off = safe_cast_u32 (dw_const_u32_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_DataMemberLocation ));
2206- }
2199+ RDIM_Type * type = d2r_find_or_convert_type (arena , type_table , input , cu , cu_lang , arch_addr_size , tag , DW_AttribKind_Type );
2200+ RDIM_UDTMember * member = rdim_udt_push_member (arena , & udts , parent -> udt );
2201+ member -> kind = RDI_MemberKind_Base ;
2202+ member -> type = type ;
2203+ member -> off = safe_cast_u32 (dw_const_u32_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_DataMemberLocation ));
22072204 } break ;
22082205 }
22092206 }
22102207 scratch_end (scratch );
22112208}
22122209
2210+ internal B8
2211+ d2r_is_udt_tag_converted (DW_TagNode * tag_node )
2212+ {
2213+ return !!(tag_node -> tag .v & D2R_TagFlags_UdtConverted );
2214+ }
2215+
2216+ internal void
2217+ d2r_flag_converted_udt_tag (DW_TagNode * tag_node )
2218+ {
2219+ tag_node -> tag .v |= D2R_TagFlags_UdtConverted ;
2220+ }
2221+
2222+ internal void
2223+ d2r_inline_anonymous_udt_member (Arena * arena , RDIM_UDT * top_udt , U64 base_off , RDIM_UDT * udt )
2224+ {
2225+ for (RDIM_UDTMember * curr = udt -> first_member , * prev = 0 ; curr != 0 ; prev = curr , curr = curr -> next ) {
2226+ if (curr -> name .size == 0 ) {
2227+ d2r_inline_anonymous_udt_member (arena , top_udt , base_off + curr -> off , curr -> type -> udt );
2228+ } else {
2229+ // copy member and adjust its offset relative to inlined position in the root UDT
2230+ RDIM_UDTMember * m = rdim_udt_push_member (arena , & udts , top_udt );
2231+ * m = * curr ;
2232+ m -> off += base_off ;
2233+ }
2234+ }
2235+ }
2236+
22132237internal void
22142238d2r_convert_udts (Arena * arena ,
22152239 D2R_TypeTable * type_table ,
@@ -2220,89 +2244,82 @@ d2r_convert_udts(Arena *arena,
22202244 DW_TagNode * root )
22212245{
22222246 Temp scratch = scratch_begin (& arena , 1 );
2247+
22232248 for (D2R_TagIterator * it = d2r_tag_iterator_init (scratch .arena , root ); it -> tag_node != 0 ; d2r_tag_iterator_next (scratch .arena , it )) {
22242249 DW_TagNode * tag_node = it -> tag_node ;
22252250 DW_Tag tag = tag_node -> tag ;
2226- switch (tag .kind ) {
2227- case DW_TagKind_ClassType : {
2228- B32 is_decl = dw_flag_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_Declaration );
2229- if (is_decl ) {
2230- d2r_tag_iterator_skip_children (it );
2231- } else {
2232- RDIM_Type * type = d2r_type_from_offset (type_table , tag .info_off );
2233- RDIM_UDT * udt = rdim_udt_chunk_list_push (arena , & udts , UDT_CHUNK_CAP );
2234- udt -> self_type = type ;
2235- type -> udt = udt ;
2236- }
2237- } break ;
2238- case DW_TagKind_StructureType : {
2239- B32 is_decl = dw_flag_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_Declaration );
2240- if (is_decl ) {
2241- d2r_tag_iterator_skip_children (it );
2242- } else {
2243- RDIM_Type * type = d2r_type_from_offset (type_table , tag .info_off );
2244- RDIM_UDT * udt = rdim_udt_chunk_list_push (arena , & udts , UDT_CHUNK_CAP );
2245- udt -> self_type = type ;
2246- type -> udt = udt ;
2247- }
2248- } break ;
2249- case DW_TagKind_UnionType : {
2250- B32 is_decl = dw_flag_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_Declaration );
2251- if (is_decl ) {
2252- d2r_tag_iterator_skip_children (it );
2253- } else {
2254- RDIM_Type * type = d2r_type_from_offset (type_table , tag .info_off );
2255- RDIM_UDT * udt = rdim_udt_chunk_list_push (arena , & udts , UDT_CHUNK_CAP );
2256- udt -> self_type = type ;
2257- type -> udt = udt ;
2258- }
2259- } break ;
2260- case DW_TagKind_EnumerationType : {
2261- B32 is_decl = dw_flag_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_Declaration );
2262- if (is_decl ) {
2263- d2r_tag_iterator_skip_children (it );
2264- } else {
2265- RDIM_Type * type = d2r_type_from_offset (type_table , tag .info_off );
2266- RDIM_UDT * udt = rdim_udt_chunk_list_push (arena , & udts , UDT_CHUNK_CAP );
2267- udt -> self_type = type ;
2268- type -> udt = udt ;
2269- }
2270- } break ;
2271- case DW_TagKind_Member : {
2272- DW_Tag parent_tag = d2r_tag_iterator_parent_tag (it );
2273- B32 is_parent_udt = parent_tag .kind == DW_TagKind_StructureType ||
2274- parent_tag .kind == DW_TagKind_ClassType ||
2275- parent_tag .kind == DW_TagKind_UnionType ;
2276- if (is_parent_udt ) {
2277- DW_Attrib * data_member_location = dw_attrib_from_tag (input , cu , tag , DW_AttribKind_DataMemberLocation );
2278- DW_AttribClass data_member_location_class = dw_value_class_from_attrib (cu , data_member_location );
2279- if (data_member_location_class == DW_AttribClass_LocList ) {
2280- AssertAlways (!"UDT member with multiple locations are not supported" );
2251+
2252+ // skip converted tags
2253+ if (d2r_is_udt_tag_converted (tag_node )) {
2254+ d2r_tag_iterator_skip_children (it );
2255+ continue ;
2256+ }
2257+ d2r_flag_converted_udt_tag (tag_node );
2258+
2259+ if (tag .kind == DW_TagKind_ClassType || tag .kind == DW_TagKind_StructureType || tag .kind == DW_TagKind_UnionType ) {
2260+ B32 is_decl = dw_flag_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_Declaration );
2261+ if (is_decl ) {
2262+ d2r_tag_iterator_skip_children (it );
2263+ } else {
2264+ RDIM_Type * type = d2r_type_from_offset (type_table , tag .info_off );
2265+ RDIM_UDT * udt = rdim_udt_chunk_list_push (arena , & udts , UDT_CHUNK_CAP );
2266+ udt -> self_type = type ;
2267+ type -> udt = udt ;
2268+ }
2269+ } else if (tag .kind == DW_TagKind_EnumerationType ) {
2270+ B32 is_decl = dw_flag_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_Declaration );
2271+ if (is_decl ) {
2272+ d2r_tag_iterator_skip_children (it );
2273+ } else {
2274+ RDIM_Type * type = d2r_type_from_offset (type_table , tag .info_off );
2275+ RDIM_UDT * udt = rdim_udt_chunk_list_push (arena , & udts , UDT_CHUNK_CAP );
2276+ udt -> self_type = type ;
2277+ type -> udt = udt ;
2278+ }
2279+ } else if (tag .kind == DW_TagKind_Member ) {
2280+ DW_Tag parent_tag = d2r_tag_iterator_parent_tag (it );
2281+ B32 is_parent_udt = parent_tag .kind == DW_TagKind_StructureType ||
2282+ parent_tag .kind == DW_TagKind_ClassType ||
2283+ parent_tag .kind == DW_TagKind_UnionType ;
2284+ if (is_parent_udt ) {
2285+ RDIM_Type * parent_type = d2r_type_from_offset (type_table , parent_tag .info_off );
2286+ RDIM_Type * type = d2r_type_from_attrib (type_table , input , cu , tag , DW_AttribKind_Type );
2287+ String8 name = dw_string_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_Name );
2288+ U64 off = dw_const_u64_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_DataMemberLocation );
2289+ if (name .size == 0 ) { // inline anonymous members
2290+ DW_Reference type_ref = dw_ref_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_Type );
2291+ RDIM_Type * member_type = d2r_type_from_offset (type_table , type_ref .info_off );
2292+ RDIM_UDT * member_udt = member_type -> udt ;
2293+ if (member_udt == 0 ) {
2294+ DW_Language ref_cu_lang = dw_const_u64_from_tag_attrib_kind (input , type_ref .cu , type_ref .cu -> tag , DW_AttribKind_Language );
2295+ DW_TagNode * ref_tag_node = dw_tag_node_from_info_off (type_ref .cu , type_ref .info_off );
2296+ d2r_convert_udts (arena , type_table , input , type_ref .cu , ref_cu_lang , arch_addr_size , ref_tag_node );
2297+ Assert (member_type -> udt );
2298+ member_udt = member_type -> udt ;
22812299 }
2282-
2283- RDIM_Type * parent_type = d2r_type_from_offset (type_table , parent_tag .info_off );
2284- RDIM_UDTMember * udt_member = rdim_udt_push_member (arena , & udts , parent_type -> udt );
2285- udt_member -> kind = RDI_MemberKind_DataField ;
2286- udt_member -> name = dw_string_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_Name );
2287- udt_member -> type = d2r_type_from_attrib (type_table , input , cu , tag , DW_AttribKind_Type );
2288- udt_member -> off = dw_const_u64_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_DataMemberLocation );
2300+ d2r_inline_anonymous_udt_member (arena , parent_type -> udt , off , member_udt );
22892301 } else {
2290- // TODO: error handling
2291- AssertAlways (!"unexpected parent tag" );
2302+ RDIM_UDTMember * member = rdim_udt_push_member (arena , & udts , parent_type -> udt );
2303+ member -> kind = RDI_MemberKind_DataField ;
2304+ member -> name = name ;
2305+ member -> type = type ;
2306+ member -> off = off ;
22922307 }
2293- } break ;
2294- case DW_TagKind_Enumerator : {
2295- DW_Tag parent_tag = d2r_tag_iterator_parent_tag (it );
2296- if (parent_tag .kind == DW_TagKind_EnumerationType ) {
2297- RDIM_Type * parent_type = d2r_type_from_offset (type_table , parent_tag .info_off );
2298- RDIM_UDTEnumVal * udt_member = rdim_udt_push_enum_val (arena , & udts , parent_type -> udt );
2299- udt_member -> name = dw_string_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_Name );
2300- udt_member -> val = dw_const_u64_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_ConstValue );
2301- } else {
2302- // TODO: error handling
2303- AssertAlways (!"unexpected parent tag" );
2304- }
2305- } break ;
2308+ } else {
2309+ // TODO: error handling
2310+ AssertAlways (!"unexpected parent tag" );
2311+ }
2312+ } else if (tag .kind == DW_TagKind_Enumerator ) {
2313+ DW_Tag parent_tag = d2r_tag_iterator_parent_tag (it );
2314+ if (parent_tag .kind == DW_TagKind_EnumerationType ) {
2315+ RDIM_Type * parent_type = d2r_type_from_offset (type_table , parent_tag .info_off );
2316+ RDIM_UDTEnumVal * udt_member = rdim_udt_push_enum_val (arena , & udts , parent_type -> udt );
2317+ udt_member -> name = dw_string_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_Name );
2318+ udt_member -> val = dw_const_u64_from_tag_attrib_kind (input , cu , tag , DW_AttribKind_ConstValue );
2319+ } else {
2320+ // TODO: error handling
2321+ AssertAlways (!"unexpected parent tag" );
2322+ }
23062323 }
23072324 }
23082325 scratch_end (scratch );
0 commit comments