switch to using 32-bit offsets for leaf records over the pointers

This commit is contained in:
Nikita Smith
2026-02-15 23:11:51 -08:00
parent 09e37a6a2e
commit 76213ec5cd
10 changed files with 347 additions and 321 deletions
+6
View File
@@ -288,6 +288,12 @@ memory_is_zero(void *ptr, U64 size)
return result;
}
internal void UBSAN_NO_ALIGN
memory_write16(void *ptr, U16 v)
{
MemoryCopy(ptr, &v, sizeof(v));
}
internal void UBSAN_NO_ALIGN
memory_write32(void *ptr, U32 v)
{
+1
View File
@@ -1009,6 +1009,7 @@ internal F32 sign_from_side_F32(Side side);
internal B32 memory_is_zero(void *ptr, U64 size);
internal void memory_write16(void *ptr, U16 v);
internal void memory_write32(void *ptr, U32 v);
internal U8 memory_read8(void *ptr);
+2
View File
@@ -1161,6 +1161,8 @@ struct CV_SymPub32
//- (SymKind: LPROC32, GPROC32)
#define CV_IsProc32(x) (x == CV_SymKind_LPROC32_ID || x == CV_SymKind_GPROC32_ID || x == CV_SymKind_LPROC32_DPC)
typedef struct CV_SymProc32 CV_SymProc32;
struct CV_SymProc32
{
+49 -102
View File
@@ -170,8 +170,10 @@ cv_deserial_leaf(String8 raw_data, U64 off, U64 align, CV_Leaf *leaf_out)
// do we have enough bytes to read header?
Assert(raw_data.size >= sizeof(CV_LeafHeader));
U8 *leaf_ptr = raw_data.str + off;
StaticAssert(sizeof(CV_LeafHeader) == 4, g_leaf_header_size_check);
CV_LeafHeader header = { .v = memory_read32(raw_data.str + off) };
CV_LeafHeader header = { .v = memory_read32(leaf_ptr) };
// leaf size must have enough bytes for the kind enum
Assert(header.size >= sizeof(CV_LeafKind));
@@ -181,7 +183,7 @@ cv_deserial_leaf(String8 raw_data, U64 off, U64 align, CV_Leaf *leaf_out)
// fill out leaf
leaf_out->kind = header.kind;
leaf_out->data = str8(raw_data.str + sizeof(CV_LeafHeader), header.size - sizeof(CV_LeafKind));
leaf_out->data = str8(leaf_ptr + sizeof(CV_LeafHeader), header.size - sizeof(CV_LeafKind));
U64 leaf_size = AlignPow2(sizeof(CV_LeafHeader) + leaf_out->data.size, align);
Assert(leaf_size <= raw_data.size);
@@ -1070,68 +1072,36 @@ cv_dedup_symbol_ptr_array(TP_Context *tp, CV_SymbolPtrArray *symbols)
//~ .debug$T helpers
internal CV_DebugT
cv_debug_t_from_data_arr(Arena *arena, String8Array data_arr, U64 align)
cv_debug_t_from_data(Arena *arena, String8 data, U64 align)
{
ProfBegin("Upfront parse");
U64 max_leaf_count = 0;
for (U64 data_idx = 0; data_idx < data_arr.count; data_idx += 1) {
String8 data = data_arr.v[data_idx];
for (U64 cursor = 0; cursor < data.size; ) {
CV_Leaf leaf;
cursor += cv_deserial_leaf(data, cursor, align, &leaf);
max_leaf_count += 1;
}
U64 count = 0;
for (U64 cursor = 0; cursor < data.size; count += 1) {
CV_Leaf leaf;
cursor += cv_deserial_leaf(data, cursor, align, &leaf);
}
ProfEnd();
U8 **leaf_arr = push_array_no_zero(arena, U8 *, max_leaf_count);
U64 leaf_count = 0;
for (U64 data_idx = 0; data_idx < data_arr.count; data_idx += 1) {
String8 data = data_arr.v[data_idx];
U32 *offsets = push_array_no_zero(arena, U32, count);
for (U64 cursor = 0, idx = 0; cursor < data.size;) {
offsets[idx++] = cursor;
U64 cursor = 0;
while (cursor < data.size) {
CV_Leaf leaf;
U64 read_size = cv_deserial_leaf(data, cursor, align, &leaf);
Assert(leaf_count < max_leaf_count);
leaf_arr[leaf_count] = str8_deserial_get_raw_ptr(data, cursor, read_size);
leaf_count += 1;
// advance cursor
cursor += read_size;
}
CV_Leaf leaf;
cursor += cv_deserial_leaf(data, cursor, align, &leaf);
}
CV_DebugT debug_t = {0};
debug_t.count = leaf_count;
debug_t.v = leaf_arr;
return debug_t;
}
internal CV_DebugT
cv_debug_t_from_data(Arena *arena, String8 data, U64 align)
{
String8Array arr = {0};
arr.count = 1;
arr.v = &data;
return cv_debug_t_from_data_arr(arena, arr, align);
return (CV_DebugT){ .count = count, .data = data, .offsets = offsets };
}
internal CV_Leaf
cv_debug_t_get_leaf(CV_DebugT debug_t, U64 leaf_idx)
{
Assert(leaf_idx < debug_t.count);
U8 *ptr = debug_t.v[leaf_idx];
String8 data = str8(ptr, max_U64);
CV_Leaf leaf;
cv_deserial_leaf(data, 0, 1, &leaf);
U64 size = cv_header_struct_size_from_leaf_kind(leaf.kind);
Assert(size <= leaf.data.size);
CV_Leaf leaf = {0};
if (debug_t.count > 0) {
Assert(leaf_idx < debug_t.count);
cv_deserial_leaf(debug_t.data, debug_t.offsets[leaf_idx], 1, &leaf);
Assert(cv_header_struct_size_from_leaf_kind(leaf.kind) <= leaf.data.size);
}
return leaf;
}
@@ -1139,83 +1109,60 @@ internal String8
cv_debug_t_get_raw_leaf(CV_DebugT debug_t, U64 leaf_idx)
{
Assert(leaf_idx < debug_t.count);
U8 *leaf_ptr = debug_t.v[leaf_idx];
CV_LeafSize size = memory_read16(debug_t.v[leaf_idx]);
return str8(leaf_ptr, sizeof(size) + size);
U8 *leaf_ptr = debug_t.data.str + debug_t.offsets[leaf_idx];
CV_LeafSize leaf_size = memory_read16(leaf_ptr);
return str8(leaf_ptr, leaf_size + sizeof(leaf_size));
}
internal CV_LeafHeader *
cv_debug_t_get_leaf_header(CV_DebugT debug_t, U64 leaf_idx)
{
Assert(leaf_idx < debug_t.count);
CV_LeafHeader *leaf_header = (CV_LeafHeader *) debug_t.v[leaf_idx];
return leaf_header;
CV_LeafHeader *header = 0;
if (leaf_idx < debug_t.count) {
header = (CV_LeafHeader *)(debug_t.data.str + debug_t.offsets[leaf_idx]);
}
return header;
}
internal B32
cv_debug_t_is_pch(CV_DebugT debug_t)
{
if (debug_t.count > 0) {
CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, 0);
return cv_is_leaf_pch(leaf.kind);
}
return 0;
return cv_is_leaf_pch(cv_debug_t_get_leaf(debug_t, 0).kind);
}
internal B32
cv_debug_t_is_type_server(CV_DebugT debug_t)
{
if (debug_t.count > 0) {
CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, 0);
return cv_is_leaf_type_server(leaf.kind);
}
return 0;
return cv_is_leaf_type_server(cv_debug_t_get_leaf(debug_t, 0).kind);
}
internal U64
cv_debug_t_array_count_leaves(U64 count, CV_DebugT *arr)
cv_debug_t_array_count_leaves(U64 count, CV_DebugT *debug_t)
{
U64 total_leaf_count = 0;
for (U64 i = 0; i < count; i += 1) {
total_leaf_count += arr[i].count;
}
return total_leaf_count;
U64 total = 0;
for EachIndex(i, count) { total += debug_t[i].count; }
return total;
}
internal
THREAD_POOL_TASK_FUNC(cv_str8_list_from_debug_t_task)
internal CV_Leaf
cv_leaf_from_ptr(U8 *ptr)
{
CV_Str8ListFromDebugT *task = raw_task;
for (U64 leaf_idx = task->ranges[task_id].min; leaf_idx < task->ranges[task_id].max; ++leaf_idx) {
String8Node *node = &task->nodes[leaf_idx];
node->string = cv_debug_t_get_raw_leaf(task->debug_t, leaf_idx);
str8_list_push_node(&task->lists[task_id], node);
}
CV_Leaf leaf = {0};
cv_deserial_leaf(str8(ptr, max_U64), 0, 1, &leaf);
return leaf;
}
internal String8List
cv_str8_list_from_debug_t_parallel(TP_Context *tp, Arena *arena, CV_DebugT debug_t)
internal U16
cv_leaf_size_from_ptr(U8 *ptr)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
CV_LeafSize size = memory_read16(ptr);
return size + sizeof(size);
}
// build lists in parallel
CV_Str8ListFromDebugT task = {0};
task.debug_t = debug_t;
task.ranges = tp_divide_work(scratch.arena, debug_t.count, tp->worker_count);
task.lists = push_array(scratch.arena, String8List, tp->worker_count);
task.nodes = push_array_no_zero(arena, String8Node, debug_t.count);
tp_for_parallel(tp, 0, tp->worker_count, cv_str8_list_from_debug_t_task, &task);
// concat output lists
String8List list = {0};
for (U64 task_id = 0; task_id < tp->worker_count; ++task_id) {
str8_list_concat_in_place(&list, &task.lists[task_id]);
}
scratch_end(scratch);
ProfEnd();
return list;
internal String8
cv_raw_leaf_from_ptr(U8 *ptr)
{
return str8(ptr, cv_leaf_size_from_ptr(ptr));
}
// $$Symbols
+3 -14
View File
@@ -255,9 +255,9 @@ typedef struct CV_DebugS
typedef struct CV_DebugT
{
U64 size;
U64 count;
U8 **v;
U64 count;
String8 data;
U32 *offsets;
} CV_DebugT;
////////////////////////////////
@@ -358,14 +358,6 @@ typedef struct
CV_StringBucket **buckets;
} CV_PackStringHashTableTask;
typedef struct
{
CV_DebugT debug_t;
Rng1U64 *ranges;
String8List *lists;
String8Node *nodes;
} CV_Str8ListFromDebugT;
////////////////////////////////
internal CV_ObjInfo cv_obj_info_from_symbol(CV_Symbol symbol);
@@ -421,7 +413,6 @@ internal String8 cv_file_chksms_from_debug_s(CV_DebugS debug_s);
////////////////////////////////
//~ .debug$T helpers
internal CV_DebugT cv_debug_t_from_data_arr(Arena *arena, String8Array data_arr, U64 align);
internal CV_DebugT cv_debug_t_from_data(Arena *arena, String8 data, U64 align);
internal CV_Leaf cv_debug_t_get_leaf(CV_DebugT debug_t, U64 leaf_idx);
internal String8 cv_debug_t_get_raw_leaf(CV_DebugT debug_t, U64 leaf_idx);
@@ -430,8 +421,6 @@ internal B32 cv_debug_t_is_pch(CV_DebugT debug_t);
internal B32 cv_debug_t_is_type_server(CV_DebugT debug_t);
internal U64 cv_debug_t_array_count_leaves(U64 count, CV_DebugT *arr);
internal String8List cv_str8_list_from_debug_t_parallel(TP_Context *tp, Arena *arena, CV_DebugT types);
////////////////////////////////
//~ Sub Section helpers
+13 -5
View File
@@ -5150,8 +5150,8 @@ lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config)
//
// CodeView
//
LNK_CodeViewInput input = lnk_make_code_view_input(tp, arena, config->io_flags, config->lib_dir_list, config->alt_pch_dirs, debug_info_objs_count, debug_info_objs);
CV_DebugT *types = lnk_import_types(tp, arena, &input);
LNK_CodeViewInput input = lnk_make_code_view_input(tp, arena, config->io_flags, config->lib_dir_list, config->alt_pch_dirs, debug_info_objs_count, debug_info_objs);
LNK_MergedTypes merged_types = lnk_merge_types(tp, arena, &input);
//
// RDI
@@ -5171,7 +5171,8 @@ lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config)
input.total_symbol_input_count,
input.symbol_inputs,
input.parsed_symbols,
types);
merged_types.count,
merged_types.v);
lnk_write_data_list_to_file_path(config->rad_debug_name, config->temp_rad_debug_name, rdi_data);
@@ -5187,7 +5188,13 @@ lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config)
lnk_timer_begin(LNK_Timer_Pdb);
if (config->pdb_hash_type_names != LNK_TypeNameHashMode_Null && config->pdb_hash_type_names != LNK_TypeNameHashMode_None) {
lnk_replace_type_names_with_hashes(tp, arena, types[CV_TypeIndexSource_TPI], config->pdb_hash_type_names, config->pdb_hash_type_name_length, config->pdb_hash_type_name_map);
lnk_replace_type_names_with_hashes(tp,
arena,
merged_types.count[CV_TypeIndexSource_TPI],
merged_types.v [CV_TypeIndexSource_TPI],
config->pdb_hash_type_names,
config->pdb_hash_type_name_length,
config->pdb_hash_type_name_map);
}
String8List pdb_data = lnk_build_pdb(tp,
@@ -5201,7 +5208,8 @@ lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config)
input.total_symbol_input_count,
input.symbol_inputs,
input.parsed_symbols,
types);
merged_types.count,
merged_types.v);
lnk_write_data_list_to_file_path(config->pdb_name, config->temp_pdb_name, pdb_data);
lnk_timer_end(LNK_Timer_Pdb);
+184 -156
View File
@@ -113,8 +113,11 @@ THREAD_POOL_TASK_FUNC(lnk_parse_debug_t_task)
U64 obj_idx = task_id;
LNK_ParseDebugTTaskData *task = raw_task;
String8Array data_arr = task->data_arr_arr[obj_idx];
CV_DebugT *debug_t = &task->debug_t_arr[obj_idx];
*debug_t = cv_debug_t_from_data_arr(arena, data_arr, CV_LeafAlign);
if (data_arr.count > 0) {
task->debug_t_arr[obj_idx] = cv_debug_t_from_data(arena, data_arr.v[0], CV_LeafAlign);
} else {
MemoryZeroStruct(&task->debug_t_arr[obj_idx]);
}
ProfEnd();
}
@@ -253,8 +256,8 @@ lnk_setup_pch(Arena *arena, U64 obj_count, LNK_Obj **obj_arr, CV_DebugT *debug_t
pch->debug_p_obj_idx = debug_p_obj_idx;
// [start_index, start_index+type_index_count)
debug_t_arr[obj_idx].count -= 1;
debug_t_arr[obj_idx].v += 1;
debug_t_arr[obj_idx].count -= 1;
debug_t_arr[obj_idx].offsets += 1;
endprecomp_arr[debug_p_obj_idx] = cv_debug_t_get_leaf_header(debug_p, precomp.leaf_count);
} else {
@@ -2112,69 +2115,74 @@ THREAD_POOL_TASK_FUNC(lnk_unbucket_raw_leaves_task)
{
LNK_CvImportTypes *task = raw_task;
for EachInRange(i, task->ranges[task_id]) {
task->types[task->ti_source].v[i] = lnk_data_from_leaf_ref(task->input, *task->unique_leaf_refs_arr[task->ti_source].v[i]).str;
LNK_LeafRef *leaf_ref_ptr = task->unique_leaf_refs_arr[task->ti_source].v[i];
task->merged_types.v[task->ti_source][i] = lnk_data_from_leaf_ref(task->input, *leaf_ref_ptr).str;
}
}
internal
THREAD_POOL_TASK_FUNC(lnk_post_process_cv_symbols_task)
THREAD_POOL_TASK_FUNC(lnk_fixup_symbols_task)
{
LNK_CvImportTypes *task = raw_task;
CV_DebugT ipi_types = task->types[CV_TypeIndexSource_IPI];
CV_TypeIndex ipi_min_type_index = task->min_type_indices[CV_TypeIndexSource_IPI];
U64 leaf_count_ipi = task->merged_types.count[CV_TypeIndexSource_IPI];
U8 **leaf_arr_ipi = task->merged_types.v [CV_TypeIndexSource_IPI];
CV_TypeIndex min_ti_ipi = task->min_type_indices [CV_TypeIndexSource_IPI];
for EachNode(symnode, CV_SymbolNode, task->input->symbol_inputs[task_id].symbol_list->first) {
CV_Symbol *symbol = &symnode->data;
if (symbol->kind == CV_SymKind_LPROC32_ID || symbol->kind == CV_SymKind_GPROC32_ID || symbol->kind == CV_SymKind_LPROC32_DPC) {
CV_SymProc32 *proc32 = (CV_SymProc32 *) symbol->data.str;
if (proc32->itype >= ipi_min_type_index) {
if ((proc32->itype - ipi_min_type_index) < ipi_types.count) {
U64 leaf_idx = proc32->itype - ipi_min_type_index;
CV_Leaf leaf = cv_debug_t_get_leaf(ipi_types, leaf_idx);
if (leaf.kind == CV_LeafKind_FUNC_ID) {
if (leaf.data.size >= sizeof(CV_LeafFuncId)) {
proc32->itype = ((CV_LeafFuncId *) leaf.data.str)->itype;
} else {
Assert(!"TODO: error handle corrupt leaf");
}
} else if (leaf.kind == CV_LeafKind_MFUNC_ID) {
if (leaf.data.size >= sizeof(CV_LeafMFuncId)) {
proc32->itype = ((CV_LeafMFuncId *) leaf.data.str)->itype;
} else {
Assert(!"TODO: error handle corrupt leaf");
}
} else {
Assert(!"TODO: erorr handle unexpected leaf type");
}
} else {
Assert("TODO: error handle corrupted type index");
}
} else {
// TODO: in some cases destructors don't have a type, need a repro
}
}
// convert symbol to final type
switch (symbol->kind) {
case CV_SymKind_LPROC32_ID: symbol->kind = CV_SymKind_LPROC32; break;
case CV_SymKind_GPROC32_ID: symbol->kind = CV_SymKind_GPROC32; break;
case CV_SymKind_LPROC32_DPC_ID: symbol->kind = CV_SymKind_LPROC32_DPC; break;
case CV_SymKind_LPROCMIPS_ID: symbol->kind = CV_SymKind_LPROCMIPS; break;
case CV_SymKind_GPROCMIPS_ID: symbol->kind = CV_SymKind_GPROCMIPS; break;
case CV_SymKind_LPROCIA64_ID: symbol->kind = CV_SymKind_LPROCIA64; break;
case CV_SymKind_GPROCIA64_ID: symbol->kind = CV_SymKind_GPROCIA64; break;
case CV_SymKind_PROC_ID_END: symbol->kind = CV_SymKind_END; break;
case CV_SymKind_LPROC32_ID: symbol->kind = CV_SymKind_LPROC32; goto fixup_id;
case CV_SymKind_GPROC32_ID: symbol->kind = CV_SymKind_GPROC32; goto fixup_id;
case CV_SymKind_LPROC32_DPC_ID: symbol->kind = CV_SymKind_LPROC32_DPC; goto fixup_id;
case CV_SymKind_LPROCMIPS_ID: symbol->kind = CV_SymKind_LPROCMIPS; goto fixup_id;
case CV_SymKind_GPROCMIPS_ID: symbol->kind = CV_SymKind_GPROCMIPS; goto fixup_id;
case CV_SymKind_LPROCIA64_ID: symbol->kind = CV_SymKind_LPROCIA64; goto fixup_id;
case CV_SymKind_GPROCIA64_ID: symbol->kind = CV_SymKind_GPROCIA64; goto fixup_id;
fixup_id:; {
CV_SymProc32 *proc32 = (CV_SymProc32 *) symbol->data.str;
if (proc32->itype < min_ti_ipi) {
// TODO: in some cases destructors don't have a type, need a repro
break;
}
if ((proc32->itype - min_ti_ipi) > leaf_count_ipi) {
Assert("TODO: error handle corrupted type index");
break;
}
U64 leaf_idx = proc32->itype - min_ti_ipi;
String8 leaf_data = str8(leaf_arr_ipi[leaf_idx], max_U64);
CV_Leaf leaf;
cv_deserial_leaf(leaf_data, 0, 1, &leaf);
U64 min_leaf_size = cv_header_struct_size_from_leaf_kind(leaf.kind);
if (min_leaf_size > leaf.data.size) {
Assert(!"TODO: error handle corrupt leaf");
break;
}
if (leaf.kind == CV_LeafKind_FUNC_ID) {
proc32->itype = ((CV_LeafFuncId *) leaf.data.str)->itype;
} else if (leaf.kind == CV_LeafKind_MFUNC_ID) {
proc32->itype = ((CV_LeafMFuncId *) leaf.data.str)->itype;
} else {
Assert(!"TODO: erorr handle unexpected leaf type");
break;
}
} break;
case CV_SymKind_PROC_ID_END: symbol->kind = CV_SymKind_END; break;
}
}
}
internal CV_DebugT *
lnk_import_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input)
internal LNK_MergedTypes
lnk_merge_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input)
{
ProfBegin("Import Types");
ProfBeginFunction();
Temp scratch = temp_begin(lnk_get_huge_arena());
U64 max_ti_list_size = sizeof(CV_TypeIndexInfo) * (max_U16 / sizeof(CV_TypeIndex));
@@ -2216,8 +2224,8 @@ lnk_import_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input)
for EachIndex(ts_idx, input->type_server_count) {
task.hashes->external_hashes[ts_idx] = push_array_no_zero(scratch.arena, U64 *, CV_TypeIndexSource_COUNT);
for EachIndex(ti_source, CV_TypeIndexSource_COUNT) {
U64 leaf_count = dim_1u64(input->external_ti_ranges[ts_idx][ti_source]);
task.hashes->external_hashes[ts_idx][ti_source] = push_array(scratch.arena, U64, leaf_count); // :zero_hash_check
U64 type_count = dim_1u64(input->external_ti_ranges[ts_idx][ti_source]);
task.hashes->external_hashes[ts_idx][ti_source] = push_array(scratch.arena, U64, type_count); // :zero_hash_check
}
}
ProfEnd();
@@ -2246,12 +2254,12 @@ lnk_import_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input)
Temp temp = temp_begin(scratch.arena);
ProfBegin("Compute Per Task Ranges");
U64 per_task_leaf_count = 10000;
U64 per_task_type_count = 10000;
LNK_LeafRangeList *leaf_ranges_per_task = push_array(temp.arena, LNK_LeafRangeList, tp->worker_count);
for (U64 i = 0, task_weight = 0, task_id = 0; i < input->internal_count; i += 1) {
CV_DebugT *debug_t = &input->merged_debug_t_p_arr[i];
for (U64 k = 0; k < debug_t->count; k += per_task_leaf_count) {
U64 cap = per_task_leaf_count - task_weight;
for (U64 k = 0; k < debug_t->count; k += per_task_type_count) {
U64 cap = per_task_type_count - task_weight;
LNK_LeafRange *leaf_range = push_array(temp.arena, LNK_LeafRange, 1);
leaf_range->range = rng_1u64(k, Min(k + cap, debug_t->count));
@@ -2262,7 +2270,7 @@ lnk_import_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input)
list->count += 1;
task_weight += dim_1u64(leaf_range->range);
if (task_weight >= per_task_leaf_count) {
if (task_weight >= per_task_type_count) {
task_id = (task_id + 1) % tp->worker_count;
task_weight = 0;
}
@@ -2371,21 +2379,20 @@ lnk_import_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input)
}
ProfEnd();
task.types = push_array(tp_temp->v[0], CV_DebugT, CV_TypeIndexSource_COUNT);
for EachIndex(ti_source, CV_TypeIndexSource_COUNT) {
LNK_LeafRefArray unique_leaf_refs = task.unique_leaf_refs_arr[ti_source];
task.ti_source = ti_source;
task.types[ti_source].count = unique_leaf_refs.count;
task.types[ti_source].v = push_array(tp_temp->v[0], U8 *, unique_leaf_refs.count);
task.ranges = tp_divide_work(scratch.arena, unique_leaf_refs.count, tp->worker_count);
task.ti_source = ti_source;
task.merged_types.count[ti_source] = unique_leaf_refs.count;
task.merged_types.v [ti_source] = push_array(tp_temp->v[0], U8 *, unique_leaf_refs.count);
task.ranges = tp_divide_work(scratch.arena, unique_leaf_refs.count, tp->worker_count);
tp_for_parallel(tp, 0, tp->worker_count, lnk_unbucket_raw_leaves_task, &task);
}
tp_for_parallel_prof(tp, 0, input->total_symbol_input_count, lnk_post_process_cv_symbols_task, &task, "Post Process CV Symbols");
tp_for_parallel_prof(tp, 0, input->total_symbol_input_count, lnk_fixup_symbols_task, &task, "fixup type indices in symbols");
temp_end(scratch);
ProfEnd();
return task.types;
return task.merged_types;
}
internal
@@ -2395,7 +2402,8 @@ THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_lenient_task)
LNK_TypeNameReplacer *task = raw_task;
Rng1U64 range = task->ranges[task_id];
CV_DebugT debug_t = task->debug_t;
U64 leaf_count = task->leaf_count;
U8 **leaf_arr = task->leaf_arr;
U64 hash_length = task->hash_length;
B32 make_map = task->make_map;
@@ -2409,8 +2417,8 @@ THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_lenient_task)
U64 hash_max_chars = hash_length*2;
char temp[128];
for (U64 leaf_idx = range.min; leaf_idx < range.max; ++leaf_idx) {
CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, leaf_idx);
for EachInRange(leaf_idx, range) {
CV_Leaf leaf = cv_leaf_from_ptr(leaf_arr[leaf_idx]);
if (leaf.kind == CV_LeafKind_STRUCTURE || leaf.kind == CV_LeafKind_CLASS) {
CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data);
@@ -2446,24 +2454,28 @@ THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_lenient_task)
udt_info.unique_name.size = size;
// update leaf header
CV_LeafHeader *header = cv_debug_t_get_leaf_header(debug_t, leaf_idx);
header->size = sizeof(CV_LeafKind) +
sizeof(CV_LeafStruct) +
numeric_size +
udt_info.name.size + 1 +
udt_info.unique_name.size + 1;
U64 new_size = sizeof(CV_LeafKind) +
sizeof(CV_LeafStruct) +
numeric_size +
udt_info.name.size + 1 +
udt_info.unique_name.size + 1;
CV_LeafHeader *header = (CV_LeafHeader *)leaf_arr[leaf_idx];
Assert(new_size <= max_U16);
memory_write16(MemberFromPtr(CV_LeafHeader, header, size), (U16)new_size);
} else {
// replace uniuqe type name with hash
udt_info.unique_name.str = udt_info.name.str + udt_info.name.size + 1;
udt_info.unique_name.size = raddbg_snprintf(udt_info.unique_name.cstr, udt_info.unique_name.size, "%llx", name_hash);
// update leaf header
CV_LeafHeader *header = cv_debug_t_get_leaf_header(debug_t, leaf_idx);
header->size = sizeof(CV_LeafKind) +
sizeof(CV_LeafStruct) +
numeric_size +
udt_info.name.size + 1 +
udt_info.unique_name.size + 1;
U64 new_size = sizeof(CV_LeafKind) +
sizeof(CV_LeafStruct) +
numeric_size +
udt_info.name.size + 1 +
udt_info.unique_name.size + 1;
CV_LeafHeader *header = (CV_LeafHeader *)leaf_arr[leaf_idx];
Assert(new_size <= max_U16);
memory_write16(MemberFromPtr(CV_LeafHeader, header, size), (U16)new_size);
}
}
}
@@ -2479,7 +2491,8 @@ THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_full_task)
LNK_TypeNameReplacer *task = raw_task;
Rng1U64 range = task->ranges[task_id];
CV_DebugT debug_t = task->debug_t;
U64 leaf_count = task->leaf_count;
U8 **leaf_arr = task->leaf_arr;
U64 hash_length = task->hash_length;
B32 make_map = task->make_map;
@@ -2492,8 +2505,8 @@ THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_full_task)
U64 hash_max_chars = hash_length*2;
for (U64 leaf_idx = range.min; leaf_idx < range.max; ++leaf_idx) {
CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, leaf_idx);
for EachInRange(leaf_idx, range) {
CV_Leaf leaf = cv_leaf_from_ptr(leaf_arr[leaf_idx]);
if (leaf.kind == CV_LeafKind_STRUCTURE || leaf.kind == CV_LeafKind_CLASS) {
CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data);
@@ -2508,7 +2521,7 @@ THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_full_task)
// hash name
U64 name_hash;
blake3_hasher hasher; blake3_hasher_init(&hasher);
blake3_hasher hasher = {0}; blake3_hasher_init(&hasher);
blake3_hasher_update(&hasher, udt_info.name.str, udt_info.name.size);
blake3_hasher_finalize(&hasher, (U8*)&name_hash, sizeof(name_hash));
@@ -2525,8 +2538,10 @@ THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_full_task)
U64 numeric_size = cv_read_numeric(leaf.data, sizeof(CV_LeafStruct), &dummy);
// update header
CV_LeafHeader *header = cv_debug_t_get_leaf_header(debug_t, leaf_idx);
header->size = sizeof(CV_LeafKind) + sizeof(CV_LeafStruct) + numeric_size + udt_info.name.size + 1;
U64 new_size = sizeof(CV_LeafKind) + sizeof(CV_LeafStruct) + numeric_size + udt_info.name.size + 1;
CV_LeafHeader *header = (CV_LeafHeader *)leaf_arr[leaf_idx];
Assert(new_size <= max_U16);
memory_write16(MemberFromPtr(CV_LeafHeader, header, size), (U16)new_size);
// discard unique name
CV_LeafStruct *lf = (CV_LeafStruct *)(header + 1);
@@ -2539,15 +2554,16 @@ THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_full_task)
}
internal void
lnk_replace_type_names_with_hashes(TP_Context *tp, TP_Arena *arena, CV_DebugT debug_t, LNK_TypeNameHashMode mode, U64 hash_length, String8 map_name)
lnk_replace_type_names_with_hashes(TP_Context *tp, TP_Arena *arena, U64 leaf_count, U8 **leaf_arr, LNK_TypeNameHashMode mode, U64 hash_length, String8 map_name)
{
ProfBeginFunction();
Temp scratch = scratch_begin(arena->v, arena->count);
// init task context
LNK_TypeNameReplacer task = {0};
task.debug_t = debug_t;
task.ranges = tp_divide_work(scratch.arena, debug_t.count, tp->worker_count);
task.leaf_count = leaf_count;
task.leaf_arr = leaf_arr;
task.ranges = tp_divide_work(scratch.arena, leaf_count, tp->worker_count);
task.hash_length = Clamp(1, hash_length, 16);
if (map_name.size > 0) {
@@ -3026,7 +3042,8 @@ lnk_build_pdb(TP_Context *tp,
U64 total_symbol_input_count,
LNK_CodeViewSymbolsInput *symbol_inputs,
CV_SymbolListArray *parsed_symbols,
CV_DebugT types[CV_TypeIndexSource_COUNT])
U64 leaf_count[CV_TypeIndexSource_COUNT],
U8 **leaf_arr [CV_TypeIndexSource_COUNT])
{
ProfBegin("PDB");
Temp scratch = scratch_begin(tp_arena->v, tp_arena->count);
@@ -3044,8 +3061,8 @@ lnk_build_pdb(TP_Context *tp,
//
// leaf data is stored in g_file_arena which has linker's life-time
// and this way we skip redundant leaf copy to the type server to make things faster
pdb_type_server_push_parallel(tp, pdb->type_servers[CV_TypeIndexSource_IPI], types[CV_TypeIndexSource_IPI]);
pdb_type_server_push_parallel(tp, pdb->type_servers[CV_TypeIndexSource_TPI], types[CV_TypeIndexSource_TPI]);
pdb_type_server_push_parallel(tp, pdb->type_servers[CV_TypeIndexSource_IPI], leaf_count[CV_TypeIndexSource_IPI], leaf_arr[CV_TypeIndexSource_IPI]);
pdb_type_server_push_parallel(tp, pdb->type_servers[CV_TypeIndexSource_TPI], leaf_count[CV_TypeIndexSource_TPI], leaf_arr[CV_TypeIndexSource_TPI]);
ProfBegin("Collect Symbols for GSI");
CV_SymbolList *gsi_list_arr = push_array(scratch.arena, CV_SymbolList, obj_count);
@@ -3279,84 +3296,92 @@ THREAD_POOL_TASK_FUNC(lnk_build_udt_name_hash_table_task)
LNK_BuildUDTNameHashTableTask *task = raw_task;
LNK_UDTNameBucket *new_bucket = 0;
for EachInRange(leaf_idx, task->ranges[task_id]) {
String8 leaf_data = str8(task->leaf_arr[leaf_idx], max_U64);
for (U64 leaf_idx = task->ranges[task_id].min; leaf_idx < task->ranges[task_id].max; ++leaf_idx) {
CV_Leaf leaf = cv_debug_t_get_leaf(task->debug_t, leaf_idx);
if (cv_is_udt(leaf.kind)) {
CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data);
if (~udt_info.props & CV_TypeProp_FwdRef) {
if (!cv_is_udt_name_anon(udt_info.name)) {
String8 name = cv_name_from_udt_info(udt_info);
U64 hash = lnk_udt_name_hash_table_hash(name);
U64 best_idx = hash % task->buckets_cap;
U64 bucket_idx = best_idx;
CV_Leaf leaf;
cv_deserial_leaf(leaf_data, 0, 1, &leaf);
if (new_bucket == 0) {
new_bucket = push_array(arena, LNK_UDTNameBucket, 1);
}
new_bucket->name = name;
new_bucket->leaf_idx = leaf_idx;
// is this UDT?
if ( ! cv_is_udt(leaf.kind)) { continue; }
B32 is_inserted_or_updated = 0;
do {
retry:;
LNK_UDTNameBucket *curr_bucket = task->buckets[bucket_idx];
// skip forward references
CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data);
if (udt_info.props & CV_TypeProp_FwdRef) { continue; }
if (curr_bucket == 0) {
LNK_UDTNameBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&task->buckets[bucket_idx], new_bucket, curr_bucket);
// skip anon UDT
if (cv_is_udt_name_anon(udt_info.name)) { continue; }
if (compare_bucket == curr_bucket) {
// success, bucket was inserted
is_inserted_or_updated = 1;
break;
}
// UDT name -> bucket index
String8 name = cv_name_from_udt_info(udt_info);
U64 hash = lnk_udt_name_hash_table_hash(name);
U64 best_idx = hash % task->buckets_cap;
U64 bucket_idx = best_idx;
// another thread took the bucket...
goto retry;
} else if (str8_match(curr_bucket->name, name, 0)) {
// there is more than one UDT with identical name, pick most recent and ignore others
// push and fill bucket
if (new_bucket == 0) { new_bucket = push_array(arena, LNK_UDTNameBucket, 1); }
new_bucket->name = name;
new_bucket->leaf_idx = leaf_idx;
if (leaf_idx < curr_bucket->leaf_idx) {
LNK_UDTNameBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&task->buckets[bucket_idx], new_bucket, curr_bucket);
if (compare_bucket == curr_bucket) {
is_inserted_or_updated = 1;
break;
}
} else {
// don't need to update, more recent leaf is in the bucket
break;
}
B32 is_inserted_or_updated = 0;
do {
retry:;
LNK_UDTNameBucket *curr_bucket = task->buckets[bucket_idx];
// another thread took the bucket...
goto retry;
}
if (curr_bucket == 0) {
LNK_UDTNameBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&task->buckets[bucket_idx], new_bucket, curr_bucket);
// advance
bucket_idx = (bucket_idx + 1) % task->buckets_cap;
} while (bucket_idx != best_idx);
if (is_inserted_or_updated) {
new_bucket = 0;
}
if (compare_bucket == curr_bucket) {
// success, bucket was inserted
is_inserted_or_updated = 1;
break;
}
// another thread took the bucket...
goto retry;
} else if (str8_match(curr_bucket->name, name, 0)) {
// there is more than one UDT with identical name, pick most recent and ignore others
if (leaf_idx < curr_bucket->leaf_idx) {
LNK_UDTNameBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&task->buckets[bucket_idx], new_bucket, curr_bucket);
if (compare_bucket == curr_bucket) {
is_inserted_or_updated = 1;
break;
}
} else {
// don't need to update, more recent leaf is in the bucket
break;
}
// another thread took the bucket...
goto retry;
}
// advance
bucket_idx = (bucket_idx + 1) % task->buckets_cap;
} while (bucket_idx != best_idx);
if (is_inserted_or_updated) {
new_bucket = 0;
}
}
}
internal LNK_UDTNameBucket **
lnk_udt_name_hash_table_from_debug_t(TP_Context *tp,
lnk_udt_name_hash_table_from_leaf_arr(TP_Context *tp,
TP_Arena *arena,
CV_DebugT debug_t,
U64 leaf_count,
U8 **leaf_arr,
U64 *buckets_cap_out)
{
Temp scratch = scratch_begin(&arena->v[0], 1);
LNK_BuildUDTNameHashTableTask task = {0};
task.debug_t = debug_t;
task.buckets_cap = (U64)((F64)debug_t.count * 1.3);
task.leaf_count = leaf_count;
task.leaf_arr = leaf_arr;
task.buckets_cap = (leaf_count * 13) / 10;
task.buckets = push_array(arena->v[0], LNK_UDTNameBucket *, task.buckets_cap);
task.ranges = tp_divide_work(scratch.arena, debug_t.count, tp->worker_count);
task.ranges = tp_divide_work(scratch.arena, leaf_count, tp->worker_count);
tp_for_parallel(tp, arena, tp->worker_count, lnk_build_udt_name_hash_table_task, &task);
*buckets_cap_out = task.buckets_cap;
scratch_end(scratch);
@@ -3543,8 +3568,8 @@ lnk_rdib_type_from_itype(LNK_ConvertTypesToRDI *task, CV_TypeIndex itype)
// try to resovle forward reference (defn might be missing)
if (itype >= tpi_range.min) {
U64 leaf_idx = itype - tpi_range.min;
CV_Leaf leaf = cv_debug_t_get_leaf(task->types[CV_TypeIndexSource_TPI], leaf_idx);
CV_Leaf leaf;
cv_deserial_leaf(str8(task->leaf_arr[CV_TypeIndexSource_TPI][itype - tpi_range.min], max_U64), 0, 1, &leaf);
if (cv_is_udt(leaf.kind)) {
CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data);
if (udt_info.props & CV_TypeProp_FwdRef) {
@@ -3590,7 +3615,7 @@ THREAD_POOL_TASK_FUNC(lnk_convert_types_to_rdi_task)
for(U64 leaf_idx = task->ranges[task_id].min; leaf_idx < task->ranges[task_id].max; ++leaf_idx) {
U64 itype = task->itype_ranges[CV_TypeIndexSource_TPI].min + leaf_idx;
CV_Leaf src = cv_debug_t_get_leaf(task->types[CV_TypeIndexSource_TPI], leaf_idx);
CV_Leaf src = cv_leaf_from_ptr(task->leaf_arr[CV_TypeIndexSource_TPI][leaf_idx]);
switch (src.kind) {
case CV_LeafKind_MODIFIER: {
@@ -3613,7 +3638,7 @@ THREAD_POOL_TASK_FUNC(lnk_convert_types_to_rdi_task)
CV_TypeIndex next_itype;
for (next_itype = ptr->itype; task->itype_ranges[CV_TypeIndexSource_TPI].min <= next_itype && next_itype < task->itype_ranges[CV_TypeIndexSource_TPI].max;) {
U64 next_leaf_idx = next_itype - task->itype_ranges[CV_TypeIndexSource_TPI].min;
CV_Leaf next_leaf = cv_debug_t_get_leaf(task->types[CV_TypeIndexSource_TPI], next_leaf_idx);
CV_Leaf next_leaf = cv_leaf_from_ptr(task->leaf_arr[CV_TypeIndexSource_TPI][next_leaf_idx]);
if (next_leaf.kind != CV_LeafKind_MODIFIER) {
break;
}
@@ -3909,7 +3934,7 @@ THREAD_POOL_TASK_FUNC(lnk_convert_types_to_rdi_task)
if (contains_1u64(task->itype_ranges[CV_TypeIndexSource_TPI], method->list_itype)) {
U64 method_list_leaf_idx = method->list_itype - task->itype_ranges[CV_TypeIndexSource_TPI].min;
CV_Leaf method_list_leaf = cv_debug_t_get_leaf(task->types[CV_TypeIndexSource_TPI], method_list_leaf_idx);
CV_Leaf method_list_leaf = cv_leaf_from_ptr(task->leaf_arr[CV_TypeIndexSource_TPI][method_list_leaf_idx]);
if (method_list_leaf.kind == CV_LeafKind_METHODLIST) {
for (U64 cursor = 0; cursor + sizeof(CV_LeafMethodListMember) <= method_list_leaf.data.size; ) {
// parse CodeView method overload info
@@ -5075,7 +5100,7 @@ THREAD_POOL_TASK_FUNC(lnk_convert_symbols_to_rdi_task)
RDIB_Type *owner = 0;
if (task->ipi_itype_range.min <= sym_inline_site->inlinee && sym_inline_site->inlinee < task->ipi_itype_range.max) {
U64 leaf_idx = sym_inline_site->inlinee - task->tpi_itype_range.min;
CV_Leaf leaf = cv_debug_t_get_leaf(task->ipi, leaf_idx);
CV_Leaf leaf = cv_leaf_from_ptr(task->leaf_arr_ipi[leaf_idx]);
if (leaf.kind == CV_LeafKind_MFUNC_ID) {
if (sizeof(CV_LeafMFuncId) <= leaf.data.size) {
CV_LeafMFuncId *mfunc_id = (CV_LeafMFuncId *) leaf.data.str;
@@ -5260,7 +5285,8 @@ lnk_build_rad_debug_info(TP_Context *tp,
U64 total_symbol_input_count,
LNK_CodeViewSymbolsInput *symbol_inputs,
CV_SymbolListArray *parsed_symbols,
CV_DebugT types[CV_TypeIndexSource_COUNT])
U64 leaf_count[CV_TypeIndexSource_COUNT],
U8 **leaf_arr [CV_TypeIndexSource_COUNT])
{
ProfBegin("RDI");
Temp scratch = scratch_begin(tp_arena->v,tp_arena->count);
@@ -5314,7 +5340,7 @@ lnk_build_rad_debug_info(TP_Context *tp,
// assing low and high type indices per source
Rng1U64 itype_ranges[CV_TypeIndexSource_COUNT];
for (U64 i = 0; i < ArrayCount(itype_ranges); ++i) {
itype_ranges[i] = rng_1u64(CV_MinComplexTypeIndex, CV_MinComplexTypeIndex + types[i].count);
itype_ranges[i] = rng_1u64(CV_MinComplexTypeIndex, CV_MinComplexTypeIndex + leaf_count[i]);
}
ProfBegin("Convert Types");
@@ -5337,13 +5363,14 @@ lnk_build_rad_debug_info(TP_Context *tp,
ProfBegin("Build UDT Name Hash Table");
// TODO: fix memory life-time
udt_name_buckets_cap = 0;
udt_name_buckets = lnk_udt_name_hash_table_from_debug_t(tp, tp_arena, types[CV_TypeIndexSource_TPI], &udt_name_buckets_cap);
udt_name_buckets = lnk_udt_name_hash_table_from_leaf_arr(tp, tp_arena, leaf_count[CV_TypeIndexSource_TPI], leaf_arr[CV_TypeIndexSource_TPI], &udt_name_buckets_cap);
ProfEnd();
ProfBegin("Convert CodeView types to RDIB Types");
LNK_ConvertTypesToRDI task = {0};
task.types = types;
MemoryCopyTyped(&task.leaf_count[0], &leaf_count[0], CV_TypeIndexSource_COUNT);
MemoryCopyTyped(&task.leaf_arr[0], &leaf_arr[0], CV_TypeIndexSource_COUNT);
task.type_cap = input.type_cap;
task.udt_cap = input.udt_cap;
task.variadic_type_ref = rdib_make_type_ref(scratch.arena, input.variadic_type);
@@ -5360,7 +5387,7 @@ lnk_build_rad_debug_info(TP_Context *tp,
task.rdib_types_params_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count);
task.rdib_udt_members_lists = push_array(scratch.arena, RDIB_UDTMemberChunkList, tp->worker_count);
task.rdib_enum_members_lists = push_array(scratch.arena, RDIB_UDTMemberChunkList, tp->worker_count);
task.ranges = tp_divide_work(scratch.arena, types[CV_TypeIndexSource_TPI].count, tp->worker_count);
task.ranges = tp_divide_work(scratch.arena, leaf_count[CV_TypeIndexSource_TPI], tp->worker_count);
tp_for_parallel(tp, tp_arena, tp->worker_count, lnk_convert_types_to_rdi_task, &task);
ProfEnd();
@@ -5443,7 +5470,8 @@ lnk_build_rad_debug_info(TP_Context *tp,
task.image_sects = image_sects;
task.obj_arr = obj_arr;
task.debug_s_arr = debug_s_arr;
task.ipi = types[CV_TypeIndexSource_IPI];
task.leaf_arr_count_ipi = leaf_count[CV_TypeIndexSource_IPI];
task.leaf_arr_ipi = leaf_arr[CV_TypeIndexSource_IPI];
task.symbol_inputs = symbol_inputs;
task.parsed_symbols = parsed_symbols;
task.ipi_itype_range = itype_ranges[CV_TypeIndexSource_IPI];
+39 -26
View File
@@ -60,6 +60,12 @@ typedef struct LNK_CodeViewInput
Rng1U64 external_obj_range;
} LNK_CodeViewInput;
typedef struct LNK_MergedTypes
{
U64 count[CV_TypeIndexSource_COUNT];
U8 **v [CV_TypeIndexSource_COUNT];
} LNK_MergedTypes;
// --- Leaf Ref ----------------------------------------------------------------
typedef enum
@@ -202,7 +208,7 @@ typedef struct
CV_SymbolList *symbol_list_arr;
CV_DebugS *debug_s_arr;
CV_DebugT *types;
LNK_MergedTypes merged_types;
} LNK_CvImportTypes;
// --- Code View Processing Trasks ---------------------------------------------
@@ -314,7 +320,8 @@ typedef struct
typedef struct
{
CV_DebugT debug_t;
U64 leaf_count;
U8 **leaf_arr;
Rng1U64 *ranges;
U64 hash_length;
B32 make_map;
@@ -332,7 +339,8 @@ typedef struct
typedef struct
{
CV_DebugT debug_t;
U64 leaf_count;
U8 **leaf_arr;
Rng1U64 *ranges;
U64 buckets_cap;
LNK_UDTNameBucket **buckets;
@@ -352,7 +360,8 @@ typedef struct
typedef struct
{
CV_DebugT *types;
U64 leaf_count[CV_TypeIndexSource_COUNT];
U8 **leaf_arr[CV_TypeIndexSource_COUNT];
U64 type_cap;
U64 udt_cap;
RDIB_TypeRef variadic_type_ref;
@@ -399,7 +408,8 @@ typedef struct
COFF_SectionHeaderArray image_sects;
LNK_Obj **obj_arr;
CV_DebugS *debug_s_arr;
CV_DebugT ipi;
U64 leaf_arr_count_ipi;
U8 **leaf_arr_ipi;
LNK_CodeViewSymbolsInput *symbol_inputs;
CV_SymbolListArray *parsed_symbols;
Rng1U64 ipi_itype_range;
@@ -466,34 +476,36 @@ internal U64 lnk_hash_from_leaf_ref(LNK_LeafHashes *hashes, LNK_LeafRef leaf_re
internal LNK_LeafRef * lnk_leaf_hash_table_insert_or_update(LNK_LeafHashTable *leaf_ht, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, U64 hash, LNK_LeafRef *new_bucket);
internal LNK_LeafRef * lnk_leaf_hash_table_search(LNK_LeafHashTable *ht, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafRef leaf_ref);
internal CV_DebugT * lnk_import_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input);
internal void lnk_replace_type_names_with_hashes(TP_Context *tp, TP_Arena *arena, CV_DebugT debug_t, LNK_TypeNameHashMode mode, U64 hash_length, String8 map_name);
internal LNK_MergedTypes lnk_merge_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input);
internal void lnk_replace_type_names_with_hashes(TP_Context *tp, TP_Arena *arena, U64 leaf_count, U8 **leaf_arr, LNK_TypeNameHashMode mode, U64 hash_length, String8 map_name);
// --- RAD Debug info ----------------------------------------------------------
internal U64 lnk_udt_name_hash_table_hash (String8 string);
internal LNK_UDTNameBucket ** lnk_udt_name_hash_table_from_debug_t(TP_Context *tp, TP_Arena *arena, CV_DebugT debug_t, U64 *buckets_cap_out);
internal LNK_UDTNameBucket * lnk_udt_name_hash_table_lookup (LNK_UDTNameBucket **buckets, U64 cap, String8 name);
internal CV_TypeIndex * lnk_build_udt_fwdmap (TP_Context *tp, Arena *arena, CV_DebugT debug_t, CV_TypeIndex ti_lo, LNK_UDTNameBucket **udt_name_buckets, U64 udt_name_buckets_cap);
internal U64 lnk_udt_name_hash_table_hash (String8 string);
internal LNK_UDTNameBucket ** lnk_udt_name_hash_table_from_leaf_arr(TP_Context *tp, TP_Arena *arena, U64 leaf_count, U8 **leaf_arr, U64 *buckets_cap_out);
internal LNK_UDTNameBucket * lnk_udt_name_hash_table_lookup (LNK_UDTNameBucket **buckets, U64 cap, String8 name);
internal CV_TypeIndex * lnk_build_udt_fwdmap (TP_Context *tp, Arena *arena, CV_DebugT debug_t, CV_TypeIndex ti_lo, LNK_UDTNameBucket **udt_name_buckets, U64 udt_name_buckets_cap);
internal RDIB_TypeRef lnk_rdib_type_from_itype (LNK_ConvertTypesToRDI *task, CV_TypeIndex itype);
internal RDI_MemberKind lnk_rdib_method_kind_from_cv_prop (CV_MethodProp prop);
internal LNK_SourceFileBucket * lnk_src_file_hash_table_hash (String8 file_path, CV_C13ChecksumKind checksum_kind, String8 checksum_bytes);
internal LNK_SourceFileBucket * lnk_src_file_hash_table_lookup_slot(LNK_SourceFileBucket **src_file_buckets, U64 src_file_buckets_cap, U64 hash, String8 file_path, CV_C13ChecksumKind checksum_kind, String8 checksum_bytes);
internal String8List lnk_build_rad_debug_info(TP_Context *tp,
TP_Arena *tp_arena,
OperatingSystem os,
RDI_Arch arch,
String8 image_name,
String8 image_data,
U64 obj_count,
LNK_Obj **obj_arr,
CV_DebugS *debug_s_arr,
U64 total_symbol_input_count,
LNK_CodeViewSymbolsInput *symbol_inputs,
CV_SymbolListArray *parsed_symbols,
CV_DebugT types[CV_TypeIndexSource_COUNT]);
internal String8List
lnk_build_rad_debug_info(TP_Context *tp,
TP_Arena *tp_arena,
OperatingSystem os,
RDI_Arch arch,
String8 image_name,
String8 image_data,
U64 obj_count,
LNK_Obj **obj_arr,
CV_DebugS *debug_s_arr,
U64 total_symbol_input_count,
LNK_CodeViewSymbolsInput *symbol_inputs,
CV_SymbolListArray *parsed_symbols,
U64 leaf_count[CV_TypeIndexSource_COUNT],
U8 **leaf_arr [CV_TypeIndexSource_COUNT]);
// --- PDB ---------------------------------------------------------------------
@@ -515,12 +527,13 @@ internal String8List lnk_build_pdb(TP_Context *tp,
U64 total_symbol_input_count,
LNK_CodeViewSymbolsInput *symbol_inputs,
CV_SymbolListArray *parsed_symbols,
CV_DebugT types[CV_TypeIndexSource_COUNT]);
U64 leaf_count[CV_TypeIndexSource_COUNT],
U8 **leaf_arr [CV_TypeIndexSource_COUNT]);
// --- RAD Debug Info ----------------------------------------------------------
internal U64 lnk_udt_name_hash_table_hash (String8 string);
internal LNK_UDTNameBucket ** lnk_udt_name_hash_table_from_debug_t(TP_Context *tp, TP_Arena *arena, CV_DebugT debug_t, U64 *buckets_cap_out);
internal LNK_UDTNameBucket ** lnk_udt_name_hash_table_from_leaf_arr(TP_Context *tp, TP_Arena *arena, U64 leaf_count, U8 **leaf_arr, U64 *buckets_cap_out);
internal LNK_UDTNameBucket * lnk_udt_name_hash_table_lookup (LNK_UDTNameBucket **buckets, U64 cap, String8 name);
internal CV_TypeIndex * lnk_build_udt_fwdmap(TP_Context *tp,
+46 -15
View File
@@ -1445,13 +1445,14 @@ internal
THREAD_POOL_TASK_FUNC(pdb_count_udt_task)
{
PDB_PushLeafTask *task = raw_task;
Rng1U64 range = task->ranges[task_id];
for (U64 leaf_idx = range.min; leaf_idx < range.max; ++leaf_idx) {
CV_Leaf leaf = cv_debug_t_get_leaf(task->debug_t, leaf_idx);
for EachInRange(leaf_idx, task->ranges[task_id]) {
CV_Leaf leaf;
cv_deserial_leaf(str8(task->leaf_arr[leaf_idx], max_U64), 0, 1, &leaf);
if (cv_is_udt(leaf.kind)) {
CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data);
if (~udt_info.props & CV_TypeProp_FwdRef) {
++task->udt_counts[task_id];
task->udt_counts[task_id] += 1;
}
}
}
@@ -1462,27 +1463,27 @@ THREAD_POOL_TASK_FUNC(pdb_push_udt_leaf_task)
{
PDB_PushLeafTask *task = raw_task;
PDB_TypeServer *type_server = task->type_server;
Rng1U64 range = task->ranges[task_id];
U64 bucket_cursor = task->udt_offsets[task_id];
CV_DebugT debug_t = task->debug_t;
PDB_TypeBucket *new_buckets = task->udt_buckets;
U64 type_ht_cap = type_server->bucket_cap;
PDB_TypeBucket **type_ht_buckets = type_server->buckets;
U64 base_type_index = type_server->ti_lo + type_server->leaf_list.node_count;
for (U64 leaf_idx = range.min; leaf_idx < range.max; ++leaf_idx) {
CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, leaf_idx);
for EachInRange(leaf_idx, task->ranges[task_id]) {
CV_Leaf leaf;
cv_deserial_leaf(str8(task->leaf_arr[leaf_idx], max_U64), 0, 1, &leaf);
if (cv_is_udt(leaf.kind)) {
CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data);
if (~udt_info.props & CV_TypeProp_FwdRef) {
// hash udt and compute bucket index
U32 hash = pdb_hash_udt(udt_info, leaf.data);
U32 hash = pdb_hash_udt(udt_info, leaf.data);
U32 bucket_idx = hash % type_ht_cap;
// fill out & insert bucket
PDB_TypeBucket *bucket = &new_buckets[bucket_cursor++];
bucket->raw_leaf = cv_debug_t_get_raw_leaf(debug_t, leaf_idx);
bucket->raw_leaf = leaf.data;
bucket->type_index = base_type_index + leaf_idx;
bucket->next = ins_atomic_ptr_eval_assign(&type_ht_buckets[bucket_idx], bucket);
}
@@ -1490,16 +1491,36 @@ THREAD_POOL_TASK_FUNC(pdb_push_udt_leaf_task)
}
}
typedef struct
{
Rng1U64 *ranges;
U8 **leaf_arr;
String8List *lists;
String8Node *nodes;
} PDB_String8ListFromLeafArray;
internal
THREAD_POOL_TASK_FUNC(pdb_str8_list_from_leaf_array_task)
{
PDB_String8ListFromLeafArray *task = raw_task;
for EachInRange(leaf_idx, task->ranges[task_id]) {
String8Node *node = &task->nodes[leaf_idx];
node->string = cv_raw_leaf_from_ptr(task->leaf_arr[leaf_idx]);
str8_list_push_node(&task->lists[task_id], node);
}
}
internal void
pdb_type_server_push_parallel(TP_Context *tp, PDB_TypeServer *type_server, CV_DebugT debug_t)
pdb_type_server_push_parallel(TP_Context *tp, PDB_TypeServer *type_server, U64 leaf_count, U8 **leaf_arr)
{
ProfBeginFunction();
Temp scratch = scratch_begin(0, 0);
PDB_PushLeafTask task = {0};
task.debug_t = debug_t;
task.leaf_count = leaf_count;
task.leaf_arr = leaf_arr;
task.type_server = type_server;
task.ranges = tp_divide_work(scratch.arena, debug_t.count, tp->worker_count);
task.ranges = tp_divide_work(scratch.arena, leaf_count, tp->worker_count);
ProfBegin("Count UDT");
task.udt_counts = push_array(scratch.arena, U64, tp->worker_count);
@@ -1514,8 +1535,18 @@ pdb_type_server_push_parallel(TP_Context *tp, PDB_TypeServer *type_server, CV_De
ProfEnd();
ProfBegin("Append New Leaves");
String8List new_leaves = cv_str8_list_from_debug_t_parallel(tp, type_server->arena, debug_t);
str8_list_concat_in_place(&type_server->leaf_list, &new_leaves);
{
PDB_String8ListFromLeafArray task = {0};
task.leaf_arr = leaf_arr;
task.ranges = tp_divide_work(scratch.arena, leaf_count, tp->worker_count);
task.lists = push_array(scratch.arena, String8List, tp->worker_count);
task.nodes = push_array_no_zero(type_server->arena, String8Node, leaf_count);
tp_for_parallel(tp, 0, tp->worker_count, pdb_str8_list_from_leaf_array_task, &task);
// concat output lists
String8List list = {0};
for EachIndex(task_id, tp->worker_count) { str8_list_concat_in_place(&type_server->leaf_list, &task.lists[task_id]); }
}
ProfEnd();
scratch_end(scratch);
+3 -2
View File
@@ -119,7 +119,8 @@ typedef struct PDB_TypeServerParse
typedef struct
{
CV_DebugT debug_t;
U64 leaf_count;
U8 **leaf_arr;
U64 *udt_counts;
U64 *udt_offsets;
Rng1U64 *ranges;
@@ -474,7 +475,7 @@ internal PDB_TypeServer * pdb_type_server_open(MSF_Context *msf, MSF_Stre
internal void pdb_type_server_build(TP_Context *tp, PDB_TypeServer *ts, PDB_StringTable *strtab, MSF_Context *msf, MSF_StreamNumber sn);
internal void pdb_type_server_release(PDB_TypeServer **serv_ptr);
internal void pdb_type_server_push(PDB_TypeServer *ts, String8 raw_leaf);
internal void pdb_type_server_push_parallel(TP_Context *tp, PDB_TypeServer *ts, CV_DebugT types);
internal void pdb_type_server_push_parallel(TP_Context *tp, PDB_TypeServer *ts, U64 leaf_count, U8 **leaf_arr);
//internal CV_LeafNode * pdb_type_server_leaf_from_string(PDB_TypeServer *ts, String8 string);
internal String8Node * pdb_type_server_reserve(PDB_TypeServer *ts, U64 count);
internal String8Node * pdb_type_server_make_leaf(PDB_TypeServer *ts, CV_LeafKind kind, String8 data);