Skip to content

Commit 81f08a0

Browse files
inline anonymous members
1 parent f8f3f95 commit 81f08a0

File tree

3 files changed

+117
-92
lines changed

3 files changed

+117
-92
lines changed

src/dwarf/dwarf_parse.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,15 @@ typedef struct DW_AttribList
125125
U64 count;
126126
} DW_AttribList;
127127

128+
typedef U8 DW_TagSpare;
128129
typedef struct DW_Tag
129130
{
130131
B32 has_children;
131132
U64 abbrev_id;
132133
DW_TagKind kind;
133134
DW_AttribList attribs;
134135
U64 info_off;
135-
U8 v[1];
136+
DW_TagSpare v;
136137
} DW_Tag;
137138

138139
typedef struct DW_TagNode

src/rdi_from_dwarf/rdi_from_dwarf.c

Lines changed: 108 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,15 +1756,15 @@ d2r_tag_iterator_parent_tag(D2R_TagIterator *iter)
17561756
}
17571757

17581758
internal 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

17641764
internal 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

17701770
internal 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+
22132237
internal void
22142238
d2r_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);

src/rdi_from_dwarf/rdi_from_dwarf.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ typedef struct D2R_TypeTable
2323
RDIM_Type **builtin_types;
2424
} D2R_TypeTable;
2525

26+
typedef DW_TagSpare D2R_TagFlags;
27+
enum
28+
{
29+
D2R_TagFlags_TypeConverted = (1 << 0),
30+
D2R_TagFlags_UdtConverted = (1 << 1),
31+
};
32+
2633
typedef struct D2R_TagFrame
2734
{
2835
DW_TagNode *node;

0 commit comments

Comments
 (0)