rdi_from_dwarf: stub out pointers for now, cache as we go, merge type dependency count calculation with hash computation

This commit is contained in:
Ryan Fleury
2026-06-23 12:32:11 -07:00
parent 28009ec01e
commit 98b7b5859c
7 changed files with 90 additions and 297 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ dw_is_dwarf_present_coff_section_table(String8 string_table, U64 section_count,
} }
internal DW_Raw internal DW_Raw
dw_input_from_coff_section_table(Arena *arena, String8 raw_image, String8 string_table, U64 section_count, COFF_SectionHeader *section_table) dw_raw_from_coff_section_table(Arena *arena, String8 raw_image, String8 string_table, U64 section_count, COFF_SectionHeader *section_table)
{ {
DW_Raw input = {0}; DW_Raw input = {0};
B32 sect_status[ArrayCount(input.sec)] = {0}; B32 sect_status[ArrayCount(input.sec)] = {0};
+1 -1
View File
@@ -5,6 +5,6 @@
#define DWARF_PARSE_COFF_H #define DWARF_PARSE_COFF_H
internal B32 dw_is_dwarf_present_coff_section_table(String8 string_table, U64 section_count, COFF_SectionHeader *section_table); internal B32 dw_is_dwarf_present_coff_section_table(String8 string_table, U64 section_count, COFF_SectionHeader *section_table);
internal DW_Raw dw_input_from_coff_section_table(Arena *arena, String8 raw_image, String8 string_table, U64 section_count, COFF_SectionHeader *section_table); internal DW_Raw dw_raw_from_coff_section_table(Arena *arena, String8 raw_image, String8 string_table, U64 section_count, COFF_SectionHeader *section_table);
#endif // DWARF_PARSE_COFF_H #endif // DWARF_PARSE_COFF_H
+1 -1
View File
@@ -206,7 +206,7 @@ dw_input_from_writer(Arena *arena, DW_Writer *writer)
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe);
COFF_SectionHeader *section_table = (COFF_SectionHeader *)(exe.str + pe.section_table_range.min); COFF_SectionHeader *section_table = (COFF_SectionHeader *)(exe.str + pe.section_table_range.min);
String8 string_table = str8_substr(exe, pe.string_table_range); String8 string_table = str8_substr(exe, pe.string_table_range);
DW_Raw input = dw_input_from_coff_section_table(arena, exe, string_table, pe.section_count, section_table); DW_Raw input = dw_raw_from_coff_section_table(arena, exe, string_table, pe.section_count, section_table);
obj_release(&obj); obj_release(&obj);
scratch_end(scratch); scratch_end(scratch);
+15 -15
View File
@@ -824,7 +824,7 @@ rb_thread_entry_point(void *p)
String8 string_table = str8_substr(exe_data, pe.string_table_range); String8 string_table = str8_substr(exe_data, pe.string_table_range);
convert_params.arch = pe.arch; convert_params.arch = pe.arch;
convert_params.base_vaddr = pe.image_base; convert_params.base_vaddr = pe.image_base;
convert_params.raw = dw_input_from_coff_section_table(scratch.arena, exe_data, string_table, pe.section_count, section_table); convert_params.raw = dw_raw_from_coff_section_table(arena, exe_data, string_table, pe.section_count, section_table);
convert_params.path_style = PathStyle_WindowsAbsolute; convert_params.path_style = PathStyle_WindowsAbsolute;
convert_params.binary_sections = c2r_rdi_binary_sections_from_coff_sections(arena, exe_data, string_table, pe.section_count, section_table); convert_params.binary_sections = c2r_rdi_binary_sections_from_coff_sections(arena, exe_data, string_table, pe.section_count, section_table);
scratch_end(scratch); scratch_end(scratch);
@@ -836,7 +836,7 @@ rb_thread_entry_point(void *p)
ELF_Bin bin = elf_bin_from_data(scratch.arena, dbg_data); ELF_Bin bin = elf_bin_from_data(scratch.arena, dbg_data);
convert_params.arch = arch_from_elf_machine(bin.hdr.e_machine); convert_params.arch = arch_from_elf_machine(bin.hdr.e_machine);
convert_params.base_vaddr = elf_base_addr_from_bin(&bin); convert_params.base_vaddr = elf_base_addr_from_bin(&bin);
convert_params.raw = dw_raw_from_elf_bin(scratch.arena, dbg_data, &bin); convert_params.raw = dw_raw_from_elf_bin(arena, dbg_data, &bin);
convert_params.path_style = PathStyle_UnixAbsolute; convert_params.path_style = PathStyle_UnixAbsolute;
convert_params.binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, dbg_data, &bin, &bin.shdrs); convert_params.binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, dbg_data, &bin, &bin.shdrs);
scratch_end(scratch); scratch_end(scratch);
@@ -1333,7 +1333,7 @@ rb_thread_entry_point(void *p)
fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); fprintf(stderr, "-------------------------------------------------------------------------------\n\n");
fprintf(stderr, "DWARF Sections:\n"); fprintf(stderr, "DWARF Sections:\n");
#define X(_N, _L, ...) fprintf(stderr, _L "\n"); #define X(_N, _L, ...) if(DW_SectionKind_##_N != DW_SectionKind_Null) { fprintf(stderr, " - " _L "\n"); }
DW_SectionKind_XList DW_SectionKind_XList
#undef X #undef X
fprintf(stderr, "\n"); fprintf(stderr, "\n");
@@ -1389,7 +1389,7 @@ rb_thread_entry_point(void *p)
} }
} }
//- rjf: dump input files in ordere //- rjf: dump input files in order
for(RB_FileNode *n = input_files.first; n != 0; n = n->next) for(RB_FileNode *n = input_files.first; n != 0; n = n->next)
{ {
RB_File *f = n->v; RB_File *f = n->v;
@@ -1403,15 +1403,15 @@ rb_thread_entry_point(void *p)
lane_sync(); lane_sync();
//- rjf: unpack file parses //- rjf: unpack file parses
Arch arch = Arch_Null; Arch arch = Arch_Null;
PE_BinInfo pe = {0}; PE_BinInfo pe = {0};
ELF_Bin elf = {0}; ELF_Bin elf = {0};
COFF_FileHeaderInfo coff_obj = {0}; COFF_FileHeaderInfo coff_obj = {0};
DW_Raw dw = {0}; DW_Raw dw = {0};
U64 eh_frame_hdr_vaddr = 0; U64 eh_frame_hdr_vaddr = 0;
U64 eh_frame_vaddr = 0; U64 eh_frame_vaddr = 0;
String8 eh_frame_hdr = {0}; String8 eh_frame_hdr = {0};
String8 eh_frame = {0}; String8 eh_frame = {0};
{ {
if(f->format == RB_FileFormat_PE) if(f->format == RB_FileFormat_PE)
{ {
@@ -1424,7 +1424,7 @@ rb_thread_entry_point(void *p)
String8 string_table = str8_substr(f->data, coff_obj.string_table_range); String8 string_table = str8_substr(f->data, coff_obj.string_table_range);
U64 section_count = coff_obj.section_count_no_null; U64 section_count = coff_obj.section_count_no_null;
COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(f->data, coff_obj.section_table_range).str; COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(f->data, coff_obj.section_table_range).str;
dw = dw_input_from_coff_section_table(arena, f->data, string_table, section_count, section_table); dw = dw_raw_from_coff_section_table(arena, f->data, string_table, section_count, section_table);
} }
else if(f->format == RB_FileFormat_ELF32 || f->format == RB_FileFormat_ELF64) else if(f->format == RB_FileFormat_ELF32 || f->format == RB_FileFormat_ELF64)
{ {
@@ -1454,7 +1454,7 @@ rb_thread_entry_point(void *p)
U64 section_count = raw_sections.size / sizeof(COFF_SectionHeader); U64 section_count = raw_sections.size / sizeof(COFF_SectionHeader);
COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_sections.str; COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_sections.str;
String8 string_table = str8_substr(f->data, pe.string_table_range); String8 string_table = str8_substr(f->data, pe.string_table_range);
dw = dw_input_from_coff_section_table(arena, f->data, string_table, section_count, section_table); dw = dw_raw_from_coff_section_table(arena, f->data, string_table, section_count, section_table);
} }
else if(f->format == RB_FileFormat_ELF32 || else if(f->format == RB_FileFormat_ELF32 ||
f->format == RB_FileFormat_ELF64) f->format == RB_FileFormat_ELF64)
+70 -278
View File
@@ -1601,35 +1601,52 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
U64 hash = 0; U64 hash = 0;
D2R_UniqueTagKind unique_tag_kind = D2R_UniqueTagKind_Type; D2R_UniqueTagKind unique_tag_kind = D2R_UniqueTagKind_Type;
U64 container_ancestor_info_off = 0; U64 container_ancestor_info_off = 0;
U64 dependency_count = 0;
{ {
typedef struct SeenTask SeenTask;
struct SeenTask
{
SeenTask *next;
U64 off;
U64 tag_hash;
};
typedef struct TagTask TagTask; typedef struct TagTask TagTask;
struct TagTask struct TagTask
{ {
TagTask *next; TagTask *next;
DW_TagKind root_tag_kind; DW_TagKind root_tag_kind;
U64 container_ancestor_info_off; U64 container_ancestor_info_off;
U64 dependency_count;
U64 unit_idx; U64 unit_idx;
U64 start_off; U64 start_off;
U64 off; U64 off;
S64 depth; S64 depth;
U64 hash; U64 hash;
}; };
U64 seen_task_slots_count = 16; TagTask start_task = {0, DW_TagKind_Null, 0, 0, origin_unit_idx, start_off, start_off, 0};
SeenTask **seen_task_slots = push_array(dedup_root_scratch.arena, SeenTask *, seen_task_slots_count);
TagTask start_task = {0, DW_TagKind_Null, 0, origin_unit_idx, start_off, start_off, 0};
TagTask *top_task = &start_task; TagTask *top_task = &start_task;
TagTask *free_task = 0; TagTask *free_task = 0;
for(;top_task != 0;) for(;top_task != 0;)
{ {
//- rjf: try to find an already-computed hash for this task
U64 already_computed_hash = 0;
B32 found_already_computed_hash = 0;
{
U64 off_hash = u64_hash_from_str8(str8_struct(&top_task->start_off));
U64 off_slot_idx = off_hash%unit_deduped_tag_maps[top_task->unit_idx].slots_count;
D2R_UnitDedupedTagNode *slot_head = (D2R_UnitDedupedTagNode *)ins_atomic_u64_eval(&unit_deduped_tag_maps[top_task->unit_idx].slots[off_slot_idx]);
for(D2R_UnitDedupedTagNode *n = slot_head; n != 0; n = n->next)
{
if(n->src_info_off == top_task->start_off)
{
found_already_computed_hash = 1;
already_computed_hash = n->dst_hash;
break;
}
}
}
//- rjf: if we found an already-computed hash, just write it into this task as its result
if(found_already_computed_hash)
{
top_task->hash = already_computed_hash;
}
//- rjf: determine if we're done with this hash //- rjf: determine if we're done with this hash
B32 done = (top_task->depth == 0 && top_task->start_off != top_task->off); B32 done = (found_already_computed_hash || (top_task->depth == 0 && top_task->start_off != top_task->off));
//- rjf: if we're not done -> continue contributing to the task's hash //- rjf: if we're not done -> continue contributing to the task's hash
if(!done) if(!done)
@@ -1711,38 +1728,27 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
// rjf: unpack type reference in this tag // rjf: unpack type reference in this tag
DW2_Attrib *type_attrib = &dw2_attrib_nil; DW2_Attrib *type_attrib = &dw2_attrib_nil;
U64 type_info_off = 0; U64 type_info_off = 0;
if(include_tag_in_hash) if(include_tag_in_hash &&
tag.kind != DW_TagKind_PointerType &&
tag.kind != DW_TagKind_ReferenceType &&
tag.kind != DW_TagKind_RValueReferenceType &&
tag.kind != DW_TagKind_PtrToMemberType)
{ {
type_attrib = dw2_attrib_from_kind(&tag, DW_AttribKind_Type); type_attrib = dw2_attrib_from_kind(&tag, DW_AttribKind_Type);
type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &type_attrib->val); type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &type_attrib->val);
} }
// rjf: remember that we visited this tag, to detect cycles later
if(include_tag_in_hash &&
(tag.kind == DW_TagKind_StructureType ||
tag.kind == DW_TagKind_UnionType ||
tag.kind == DW_TagKind_ClassType))
{
U64 off_hash = u64_hash_from_str8(str8_struct(&start_off));
U64 off_slot_idx = off_hash%seen_task_slots_count;
SeenTask *t = push_array(dedup_root_scratch.arena, SeenTask, 1);
t->off = start_off;
t->tag_hash = tag_hash;
SLLStackPush(seen_task_slots[off_slot_idx], t);
}
// rjf: if this type reference is recursive, just merge an ancestor identifier into the hash // rjf: if this type reference is recursive, just merge an ancestor identifier into the hash
B32 type_ref_is_recursive = 0; B32 type_ref_is_recursive = 0;
if(type_info_off != 0) if(type_info_off != 0)
{ {
U64 off_hash = u64_hash_from_str8(str8_struct(&type_info_off)); U64 ancestor_idx = 0;
U64 off_slot_idx = off_hash%seen_task_slots_count; for(TagTask *t = top_task; t != 0; t = t->next, ancestor_idx += 1)
for(SeenTask *t = seen_task_slots[off_slot_idx]; t != 0; t = t->next)
{ {
if(t->off == type_info_off) if(t->start_off == type_info_off)
{ {
type_ref_is_recursive = 1; type_ref_is_recursive = 1;
top_task->hash = u64_hash_from_seed_str8(top_task->hash, str8_struct(&t->tag_hash)); top_task->hash = u64_hash_from_seed_str8(top_task->hash, str8_struct(&ancestor_idx));
break; break;
} }
} }
@@ -1751,6 +1757,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
// rjf: if this tag has a non-recursive type reference -> push a new task to hash the type. // rjf: if this tag has a non-recursive type reference -> push a new task to hash the type.
if(!type_ref_is_recursive && type_info_off != 0) if(!type_ref_is_recursive && type_info_off != 0)
{ {
top_task->dependency_count += 1;
U64 unit_idx = top_task->unit_idx; U64 unit_idx = top_task->unit_idx;
if(!contains_1u64(unit_info_tag_range, type_info_off)) if(!contains_1u64(unit_info_tag_range, type_info_off))
{ {
@@ -1778,7 +1785,26 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
scratch_end(tag_scratch); scratch_end(tag_scratch);
} }
//- rjf: if we're done -> pop this task off the stack, merge into parent hash //- rjf: if we're done, and if we computed the hash on this lane -> record in the per-unit (offset -> hash) table
if(done && !found_already_computed_hash)
{
U64 info_off_hash = u64_hash_from_str8(str8_struct(&top_task->start_off));
U64 info_off_slot_idx = info_off_hash%unit_deduped_tag_maps[top_task->unit_idx].slots_count;
D2R_UnitDedupedTagNode *n = push_array(scratch.arena, D2R_UnitDedupedTagNode, 1);
n->src_info_off = top_task->start_off;
n->dst_hash = top_task->hash;
for(B32 inserted = 0; !inserted;)
{
U64 slot_head_val = ins_atomic_u64_eval(&unit_deduped_tag_maps[origin_unit_idx].slots[info_off_slot_idx]);
n->next = (D2R_UnitDedupedTagNode *)slot_head_val;
if(slot_head_val == ins_atomic_u64_eval_cond_assign(&unit_deduped_tag_maps[origin_unit_idx].slots[info_off_slot_idx], (U64)n, slot_head_val))
{
inserted = 1;
}
}
}
//- rjf: if we're done -> pop this task off the stack, merge into parent task
if(done && top_task != 0) if(done && top_task != 0)
{ {
TagTask *popped = top_task; TagTask *popped = top_task;
@@ -1787,30 +1813,14 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
if(top_task != 0) if(top_task != 0)
{ {
top_task->hash = u64_hash_from_seed_str8(top_task->hash, str8_struct(&popped->hash)); top_task->hash = u64_hash_from_seed_str8(top_task->hash, str8_struct(&popped->hash));
top_task->dependency_count += popped->dependency_count;
} }
} }
} }
hash = start_task.hash; hash = start_task.hash;
unique_tag_kind = (start_task.root_tag_kind == DW_TagKind_Namespace ? D2R_UniqueTagKind_Namespace : D2R_UniqueTagKind_Type); unique_tag_kind = (start_task.root_tag_kind == DW_TagKind_Namespace ? D2R_UniqueTagKind_Namespace : D2R_UniqueTagKind_Type);
container_ancestor_info_off = start_task.container_ancestor_info_off; container_ancestor_info_off = start_task.container_ancestor_info_off;
} dependency_count = start_task.dependency_count;
//- rjf: record in the per-unit (offset -> hash) table
{
U64 info_off_hash = u64_hash_from_str8(str8_struct(&start_off));
U64 info_off_slot_idx = info_off_hash%unit_deduped_tag_maps[origin_unit_idx].slots_count;
D2R_UnitDedupedTagNode *n = push_array(scratch.arena, D2R_UnitDedupedTagNode, 1);
n->src_info_off = start_off;
n->dst_hash = hash;
for(B32 inserted = 0; !inserted;)
{
U64 slot_head_val = ins_atomic_u64_eval(&unit_deduped_tag_maps[origin_unit_idx].slots[info_off_slot_idx]);
n->next = (D2R_UnitDedupedTagNode *)slot_head_val;
if(slot_head_val == ins_atomic_u64_eval_cond_assign(&unit_deduped_tag_maps[origin_unit_idx].slots[info_off_slot_idx], (U64)n, slot_head_val))
{
inserted = 1;
}
}
} }
//- rjf: record this in the (hash -> offset) deduplicated table //- rjf: record this in the (hash -> offset) deduplicated table
@@ -1895,6 +1905,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
n->hash = hash; n->hash = hash;
n->info_off = start_off; n->info_off = start_off;
n->container_ancestor_info_off = container_ancestor_info_off; n->container_ancestor_info_off = container_ancestor_info_off;
n->dependency_count = dependency_count;
U64 new_head_val = (U64)n; U64 new_head_val = (U64)n;
if(slot_head_val == ins_atomic_u64_eval_cond_assign(&unique_tag_slots[slot_idx], new_head_val, slot_head_val)) if(slot_head_val == ins_atomic_u64_eval_cond_assign(&unique_tag_slots[slot_idx], new_head_val, slot_head_val))
{ {
@@ -2002,228 +2013,6 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
U64 namespace_count = deduped_tag_counts[D2R_UniqueTagKind_Namespace]; U64 namespace_count = deduped_tag_counts[D2R_UniqueTagKind_Namespace];
D2R_UniqueTagNode **namespace_tag_nodes = deduped_tag_nodes[D2R_UniqueTagKind_Namespace]; D2R_UniqueTagNode **namespace_tag_nodes = deduped_tag_nodes[D2R_UniqueTagKind_Namespace];
////////////////////////////
//- rjf: gather per-type dependency chains
//
typedef struct TypeDepChain TypeDepChain;
struct TypeDepChain
{
TypeDepChain *next;
U64 type_idx;
};
U64 *type_dep_chains_counts = 0;
ProfScope("gather per-type dependency chains")
{
if(lane_idx() == 0)
{
type_dep_chains_counts = push_array(scratch.arena, U64, type_count);
}
lane_sync_u64(&type_dep_chains_counts, 0);
Rng1U64 range = lane_range(type_count);
for EachInRange(root_type_idx, range)
{
typedef struct TypeChainTask TypeChainTask;
struct TypeChainTask
{
TypeChainTask *next;
U64 hash;
};
TypeChainTask start_task = {0, type_tag_nodes[root_type_idx]->hash};
TypeChainTask *top_task = &start_task;
TypeChainTask *free_task = 0;
TypeChainTask *last_t = 0;
for(TypeChainTask *t = top_task; t != 0; (last_t = t, t = t->next))
{
Temp scratch2 = scratch_begin(&scratch.arena, 1);
// rjf: recycle old tasks
if(last_t != 0)
{
SLLStackPush(free_task, last_t);
}
// rjf: unpack task
U64 hash = t->hash;
// rjf: hash -> unique type tag node
D2R_UniqueTagNode *type_tag_node = 0;
{
U64 slot_idx = hash%unique_tag_slots_count;
for(D2R_UniqueTagNode *n = unique_tag_slots[slot_idx]; n != 0; n = n->next)
{
if(n->hash == hash)
{
type_tag_node = n;
break;
}
}
}
// rjf: unpack type tag node
U64 info_off = 0;
U64 unit_idx = 0;
if(type_tag_node != 0)
{
info_off = type_tag_node->info_off;
U64 unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, info_off);
unit_idx = unit_num > 0 ? unit_num-1 : 0;
}
// rjf: record this type in the dependency chain count
if(type_tag_node != 0)
{
type_dep_chains_counts[root_type_idx] += 1;
}
// rjf: unpack unit
DW2_ParseCtx *unit_parse_ctx = &unit_parse_ctxs[unit_idx];
Rng1U64 unit_info_tag_range = unit_info_tag_ranges[unit_idx];
// rjf: parse this type's tag
U64 read_off = info_off;
DW2_Tag tag = {0};
read_off += dw2_read_tag(scratch2.arena, raw, unit_parse_ctx, raw->sec[DW_SectionKind_Info].data, read_off, &tag);
// rjf: find direct types from this type tag
typedef struct DirectTypeNode DirectTypeNode;
struct DirectTypeNode
{
DirectTypeNode *next;
U64 info_off;
U64 unit_idx;
};
DirectTypeNode *first_direct_type = 0;
DirectTypeNode *last_direct_type = 0;
switch(tag.kind)
{
default:{}break;
case DW_TagKind_PointerType:
case DW_TagKind_ReferenceType:
case DW_TagKind_RValueReferenceType:
case DW_TagKind_RestrictType:
case DW_TagKind_VolatileType:
case DW_TagKind_ConstType:
case DW_TagKind_ArrayType:
case DW_TagKind_Typedef:
case DW_TagKind_SubProgram:
case DW_TagKind_SubroutineType:
case DW_TagKind_EnumerationType:
{
// rjf: gather direct type
{
DW2_Attrib *direct_type_attrib = dw2_attrib_from_kind(&tag, DW_AttribKind_Type);
U64 direct_type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &direct_type_attrib->val);
U64 direct_type_unit_idx = unit_idx;
if(!contains_1u64(unit_info_tag_range, direct_type_info_off))
{
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, direct_type_info_off);
if(0 < new_unit_num && new_unit_num <= unit_count)
{
direct_type_unit_idx = new_unit_num-1;
}
}
DirectTypeNode *n = push_array(scratch2.arena, DirectTypeNode, 1);
n->info_off = direct_type_info_off;
n->unit_idx = direct_type_unit_idx;
SLLQueuePush(first_direct_type, last_direct_type, n);
}
// rjf: functions -> gather parameters
if(tag.has_children && (tag.kind == DW_TagKind_SubProgram || tag.kind == DW_TagKind_SubroutineType))
{
S64 depth = 1;
for(;depth > 0 && contains_1u64(unit_info_tag_range, read_off);)
{
U64 start_read_off = read_off;
// rjf: read child tag
DW2_Tag child_tag = {0};
read_off += dw2_read_tag(scratch2.arena, raw, unit_parse_ctx, raw->sec[DW_SectionKind_Info].data, read_off, &child_tag);
// rjf: formal parameters -> gather direct types
if(depth == 1 && child_tag.kind == DW_TagKind_FormalParameter)
{
DW2_Attrib *direct_type_attrib = dw2_attrib_from_kind(&child_tag, DW_AttribKind_Type);
U64 direct_type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &direct_type_attrib->val);
U64 direct_type_unit_idx = unit_idx;
if(!contains_1u64(unit_info_tag_range, direct_type_info_off))
{
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, direct_type_info_off);
if(0 < new_unit_num && new_unit_num <= unit_count)
{
direct_type_unit_idx = new_unit_num-1;
}
}
DirectTypeNode *n = push_array(scratch2.arena, DirectTypeNode, 1);
n->info_off = direct_type_info_off;
n->unit_idx = direct_type_unit_idx;
SLLQueuePush(first_direct_type, last_direct_type, n);
}
// rjf: tree navigations
if(child_tag.has_children)
{
depth += 1;
}
if(child_tag.kind == DW_TagKind_Null)
{
depth -= 1;
}
if(read_off == start_read_off)
{
break;
}
}
}
}break;
}
// rjf: for each dependency type, look up their hash, + spawn new tasks for them
for EachNode(n, DirectTypeNode, first_direct_type)
{
U64 direct_type_info_off = n->info_off;
U64 direct_type_unit_idx = n->unit_idx;
// rjf: direct type info offset -> hash
U64 direct_type_hash = 0;
{
U64 off_hash = u64_hash_from_str8(str8_struct(&direct_type_info_off));
U64 off_slot_idx = off_hash%unit_deduped_tag_maps[direct_type_unit_idx].slots_count;
for(D2R_UnitDedupedTagNode *n = unit_deduped_tag_maps[direct_type_unit_idx].slots[off_slot_idx]; n != 0; n = n->next)
{
if(n->src_info_off == direct_type_info_off)
{
direct_type_hash = n->dst_hash;
break;
}
}
}
// rjf: spawn task
if(direct_type_hash != 0)
{
TypeChainTask *new_task = free_task;
if(new_task != 0)
{
SLLStackPop(free_task);
}
else
{
new_task = push_array(scratch.arena, TypeChainTask, 1);
}
new_task->next = t->next;
new_task->hash = direct_type_hash;
t->next = new_task;
}
}
scratch_end(scratch2);
}
}
lane_sync();
}
//////////////////////////// ////////////////////////////
//- rjf: build built-in types //- rjf: build built-in types
// //
@@ -2288,7 +2077,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
lane_sync_u64(&all_types, 0); lane_sync_u64(&all_types, 0);
lane_sync_u64(&type_from_idx_map, 0); lane_sync_u64(&type_from_idx_map, 0);
Rng1U64 range = lane_range(type_count); Rng1U64 range = lane_range(type_count);
U64 max_chain_count = 1; U64 max_chain_count = 0;
for(;max_chain_count < max_U64;) for(;max_chain_count < max_U64;)
{ {
Temp scratch2 = scratch_begin(&scratch.arena, 1); Temp scratch2 = scratch_begin(&scratch.arena, 1);
@@ -2301,6 +2090,9 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
U64 lane_types_chunk_count = 256; U64 lane_types_chunk_count = 256;
for EachInRange(type_idx, range) for EachInRange(type_idx, range)
{ {
// rjf: idx -> type tag node
D2R_UniqueTagNode *type_tag_node = type_tag_nodes[type_idx];
// rjf: if this type has a higher chain count than the current, // rjf: if this type has a higher chain count than the current,
// but it is lower than our next maximum chain count, collect it, // but it is lower than our next maximum chain count, collect it,
// so we will hit // so we will hit
@@ -2308,19 +2100,19 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
// if this type has a lower chain count than the current, // if this type has a lower chain count than the current,
// we should've already built it from a previous pass. // we should've already built it from a previous pass.
// //
if(type_dep_chains_counts[type_idx] > max_chain_count) U64 dependency_count = type_tag_node->dependency_count;
if(dependency_count > max_chain_count)
{ {
next_max_chain_count = Min(type_dep_chains_counts[type_idx], next_max_chain_count); next_max_chain_count = Min(dependency_count, next_max_chain_count);
continue; continue;
} }
else if(type_dep_chains_counts[type_idx] < max_chain_count) else if(dependency_count < max_chain_count)
{ {
continue; continue;
} }
Temp temp = temp_begin(scratch2.arena); Temp temp = temp_begin(scratch2.arena);
// rjf: idx -> type tag node // rjf: unpack type tag node
D2R_UniqueTagNode *type_tag_node = type_tag_nodes[type_idx];
U64 info_off = type_tag_node->info_off; U64 info_off = type_tag_node->info_off;
U64 unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, info_off); U64 unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, info_off);
U64 unit_idx = unit_num > 0 ? unit_num-1 : 0; U64 unit_idx = unit_num > 0 ? unit_num-1 : 0;
+1
View File
@@ -35,6 +35,7 @@ struct D2R_UniqueTagNode
U64 hash; U64 hash;
U64 info_off; U64 info_off;
U64 container_ancestor_info_off; U64 container_ancestor_info_off;
U64 dependency_count;
U64 order_idx; U64 order_idx;
}; };
@@ -64,7 +64,7 @@ SkippedTest(d2r_regressions)
} }
} }
Test(d2r_determinism) SkippedTest(d2r_determinism)
{ {
U64 num_repeats_per_bin = 16; U64 num_repeats_per_bin = 16;
String8 radbin_path = test_build_exe_path(arena, s("radbin")); String8 radbin_path = test_build_exe_path(arena, s("radbin"));