WIP fix lib push order and sort new inputs

This commit is contained in:
Nikita Smith
2025-09-05 15:19:30 -07:00
committed by Ryan Fleury
parent 67e66dc26e
commit b64e1dca9a
7 changed files with 118 additions and 100 deletions
+2
View File
@@ -16,6 +16,7 @@
</Type> </Type>
<Type Name="LNK_ExportParseList"> <Type Name="LNK_ExportParseList">
<AlternativeType Name="LNK_InputObjList"/>
<DisplayString>{{count={count} first={first} last={last} }}</DisplayString> <DisplayString>{{count={count} first={first} last={last} }}</DisplayString>
<Expand> <Expand>
<LinkedListItems> <LinkedListItems>
@@ -33,6 +34,7 @@
<AlternativeType Name="LNK_ExportParseList"/> <AlternativeType Name="LNK_ExportParseList"/>
<AlternativeType Name="LNK_InputImportList"/> <AlternativeType Name="LNK_InputImportList"/>
<AlternativeType Name="LNK_ObjList"/> <AlternativeType Name="LNK_ObjList"/>
<AlternativeType Name="LNK_InputImportList"/>
<AlternativeType Name="CV_SymbolList"/> <AlternativeType Name="CV_SymbolList"/>
<DisplayString>{{count={count} first={first} }}</DisplayString> <DisplayString>{{count={count} first={first} }}</DisplayString>
<Expand> <Expand>
+55 -8
View File
@@ -1626,7 +1626,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
if (lnk_get_log_status(LNK_Log_InputLib)) { if (lnk_get_log_status(LNK_Log_InputLib)) {
if (libs.count > 0) { if (libs.count > 0) {
U64 input_size = 0; U64 input_size = 0;
for EachIndex(i, libs.count) { input_size += libs.v[i].data.data.size; } for EachIndex(i, libs.count) { input_size += libs.v[i]->data.data.size; }
lnk_log(LNK_Log_InputObj, "[ Lib Input Size %M ]", input_size); lnk_log(LNK_Log_InputObj, "[ Lib Input Size %M ]", input_size);
} }
} }
@@ -1658,6 +1658,8 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
} break; } break;
case State_SearchUndefined: { case State_SearchUndefined: {
ProfBegin("Search Undefined"); ProfBegin("Search Undefined");
LNK_InputImportList new_imports = {0};
LNK_InputObjList new_objs = {0};
for EachIndex(i, ArrayCount(lib_index)) { for EachIndex(i, ArrayCount(lib_index)) {
for (LNK_LibNode *lib_n = lib_index[i].first; lib_n != 0; lib_n = lib_n->next) { for (LNK_LibNode *lib_n = lib_index[i].first; lib_n != 0; lib_n = lib_n->next) {
for EachIndex(worker_id, symtab->arena->count) { for EachIndex(worker_id, symtab->arena->count) {
@@ -1669,22 +1671,38 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
if (symbol_interp == COFF_SymbolValueInterp_Undefined) { if (symbol_interp == COFF_SymbolValueInterp_Undefined) {
U32 member_idx; U32 member_idx;
if (lnk_search_lib(&lib_n->data, symbol->name, &member_idx)) { if (lnk_search_lib(&lib_n->data, symbol->name, &member_idx)) {
lnk_queue_lib_member_for_input(scratch.arena, config, symbol, &lib_n->data, member_idx, &input_import_list, &input_obj_list); lnk_queue_lib_member_for_input(scratch.arena, config, symbol, &lib_n->data, member_idx, &new_imports, &new_objs);
} }
} }
} }
} }
} }
if (input_import_list.count || input_obj_list.count) { if (new_imports.count || new_objs.count) {
goto end_search_undefined; goto end_search_undefined;
} }
} }
} }
end_search_undefined:; end_search_undefined:;
{
LNK_InputImportNode **import_nodes = lnk_input_import_arr_from_list(scratch.arena, new_imports);
radsort(import_nodes, new_imports.count, lnk_input_import_is_before);
new_imports = lnk_list_from_input_import_arr(import_nodes, new_imports.count);
LNK_InputObj **obj_nodes = lnk_array_from_input_obj_list(scratch.arena, new_objs);
radsort(obj_nodes, new_objs.count, lnk_input_obj_compar_is_before);
new_objs = lnk_list_from_input_obj_arr(obj_nodes, new_objs.count);
lnk_input_import_list_concat_in_place(&input_import_list, &new_imports);
lnk_input_obj_list_concat_in_place(&input_obj_list, &new_objs);
}
ProfEnd(); ProfEnd();
} break; } break;
case State_SearchWeak: { case State_SearchWeak: {
ProfBegin("Search Weak"); ProfBegin("Search Weak");
LNK_InputImportList new_imports = {0};
LNK_InputObjList new_objs = {0};
for EachIndex(i, ArrayCount(lib_index)) { for EachIndex(i, ArrayCount(lib_index)) {
for (LNK_LibNode *lib_n = lib_index[i].first; lib_n != 0; lib_n = lib_n->next) { for (LNK_LibNode *lib_n = lib_index[i].first; lib_n != 0; lib_n = lib_n->next) {
for EachIndex(worker_id, symtab->arena->count) { for EachIndex(worker_id, symtab->arena->count) {
@@ -1698,23 +1716,39 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) { if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) {
U32 member_idx; U32 member_idx;
if (lnk_search_lib(&lib_n->data, symbol->name, &member_idx)) { if (lnk_search_lib(&lib_n->data, symbol->name, &member_idx)) {
lnk_queue_lib_member_for_input(scratch.arena, config, symbol, &lib_n->data, member_idx, &input_import_list, &input_obj_list); lnk_queue_lib_member_for_input(scratch.arena, config, symbol, &lib_n->data, member_idx, &new_imports, &new_objs);
} }
} }
} }
} }
} }
} }
if (input_import_list.count || input_obj_list.count) { if (new_imports.count || new_objs.count) {
goto end_search_weak; goto end_search_weak;
} }
} }
} }
end_search_weak:; end_search_weak:;
{
LNK_InputImportNode **import_nodes = lnk_input_import_arr_from_list(scratch.arena, new_imports);
radsort(import_nodes, new_imports.count, lnk_input_import_is_before);
new_imports = lnk_list_from_input_import_arr(import_nodes, new_imports.count);
LNK_InputObj **obj_nodes = lnk_array_from_input_obj_list(scratch.arena, new_objs);
radsort(obj_nodes, new_objs.count, lnk_input_obj_compar_is_before);
new_objs = lnk_list_from_input_obj_arr(obj_nodes, new_objs.count);
lnk_input_import_list_concat_in_place(&input_import_list, &new_imports);
lnk_input_obj_list_concat_in_place(&input_obj_list, &new_objs);
}
ProfEnd(); ProfEnd();
} break; } break;
case State_SearchWeakAntiDep: { case State_SearchWeakAntiDep: {
ProfBegin("Search Weak AntiDep"); ProfBegin("Search Weak AntiDep");
LNK_InputImportList new_imports = {0};
LNK_InputObjList new_objs = {0};
for EachIndex(i, ArrayCount(lib_index)) { for EachIndex(i, ArrayCount(lib_index)) {
for (LNK_LibNode *lib_n = lib_index[i].first; lib_n != 0; lib_n = lib_n->next) { for (LNK_LibNode *lib_n = lib_index[i].first; lib_n != 0; lib_n = lib_n->next) {
for EachIndex(worker_id, symtab->arena->count) { for EachIndex(worker_id, symtab->arena->count) {
@@ -1732,7 +1766,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
if (dep_interp == COFF_SymbolValueInterp_Weak) { if (dep_interp == COFF_SymbolValueInterp_Weak) {
U32 member_idx; U32 member_idx;
if (lnk_search_lib(&lib_n->data, symbol_parsed.name, &member_idx)) { if (lnk_search_lib(&lib_n->data, symbol_parsed.name, &member_idx)) {
lnk_queue_lib_member_for_input(scratch.arena, config, symbol, &lib_n->data, member_idx, &input_import_list, &input_obj_list); lnk_queue_lib_member_for_input(scratch.arena, config, symbol, &lib_n->data, member_idx, &new_imports, &new_objs);
} }
} }
} }
@@ -1740,13 +1774,26 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
} }
} }
} }
if (new_imports.count || new_objs.count) {
if (input_import_list.count || input_obj_list.count) {
goto end_search_antidep; goto end_search_antidep;
} }
} }
} }
end_search_antidep:; end_search_antidep:;
{
LNK_InputImportNode **import_nodes = lnk_input_import_arr_from_list(scratch.arena, new_imports);
radsort(import_nodes, new_imports.count, lnk_input_import_is_before);
new_imports = lnk_list_from_input_import_arr(import_nodes, new_imports.count);
LNK_InputObj **obj_nodes = lnk_array_from_input_obj_list(scratch.arena, new_objs);
radsort(obj_nodes, new_objs.count, lnk_input_obj_compar_is_before);
new_objs = lnk_list_from_input_obj_arr(obj_nodes, new_objs.count);
lnk_input_import_list_concat_in_place(&input_import_list, &new_imports);
lnk_input_obj_list_concat_in_place(&input_obj_list, &new_objs);
}
ProfEnd(); ProfEnd();
} break; } break;
case State_SearchEntryPoint: { case State_SearchEntryPoint: {
+4 -9
View File
@@ -84,20 +84,15 @@ lnk_path_array_from_input_obj_array(Arena *arena, LNK_InputObj **arr, U64 count)
internal int internal int
lnk_input_obj_compar(const void *raw_a, const void *raw_b) lnk_input_obj_compar(const void *raw_a, const void *raw_b)
{ {
const LNK_InputObj **a = (const LNK_InputObj **) raw_a; LNK_InputObj * const *a = raw_a, * const *b = raw_b;
const LNK_InputObj **b = (const LNK_InputObj **) raw_b; return u64_compar(&(*a)->input_idx, &(*b)->input_idx);
int cmp = str8_compar_case_sensitive(&(*a)->path, &(*b)->path);
return cmp;
} }
internal int internal int
lnk_input_obj_compar_is_before(void *raw_a, void *raw_b) lnk_input_obj_compar_is_before(void *raw_a, void *raw_b)
{ {
LNK_InputObj **a = raw_a; LNK_InputObj **a = raw_a, **b = raw_b;
LNK_InputObj **b = raw_b; return lnk_input_obj_compar(a, b) < 0;
int cmp = str8_compar_case_sensitive(&(*a)->path, &(*b)->path);
int is_before = cmp < 0;
return is_before;
} }
internal LNK_InputObjList internal LNK_InputObjList
+4 -4
View File
@@ -36,15 +36,15 @@ typedef struct LNK_InputImportList
typedef struct LNK_InputObj typedef struct LNK_InputObj
{ {
struct LNK_InputObj *next; String8 path;
String8 dedup_id;
String8 data;
B8 is_thin; B8 is_thin;
B8 exclude_from_debug_info; B8 exclude_from_debug_info;
B8 has_disk_read_failed; B8 has_disk_read_failed;
String8 dedup_id;
String8 path;
String8 data;
struct LNK_Lib *lib; struct LNK_Lib *lib;
U64 input_idx; U64 input_idx;
struct LNK_InputObj *next;
} LNK_InputObj; } LNK_InputObj;
typedef struct LNK_InputObjList typedef struct LNK_InputObjList
+28 -62
View File
@@ -1,56 +1,17 @@
// Copyright (c) 2025 Epic Games Tools // Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
internal LNK_LibNode * internal int
lnk_lib_list_pop_node_atomic(LNK_LibList *list) lnk_lib_node_is_before(void *a, void *b)
{ {
for (;;) { return ((LNK_LibNode*)a)->data.input_idx < ((LNK_LibNode*)b)->data.input_idx;
LNK_LibNode *expected = list->first;
LNK_LibNode *current = ins_atomic_ptr_eval_cond_assign(&list->first, expected->next, expected);
if (expected == current) {
ins_atomic_u64_dec_eval(&list->count);
return expected;
}
}
} }
internal void internal int
lnk_lib_list_push_node_atomic(LNK_LibList *list, LNK_LibNode *node) lnk_lib_node_ptr_is_before(void *raw_a, void *raw_b)
{ {
for (;;) { LNK_LibNode **a = raw_a, **b = raw_b;
LNK_LibNode *expected = list->first; return lnk_lib_node_is_before(*a, *b);
LNK_LibNode *current = ins_atomic_ptr_eval_cond_assign(&list->first, node, expected);
if (current == expected) {
node->next = expected;
ins_atomic_u64_inc_eval(&list->count);
return;
}
}
}
internal void
lnk_lib_list_push_node(LNK_LibList *list, LNK_LibNode *node)
{
SLLStackPush(list->first, node);
list->count += 1;
}
internal LNK_LibList
lnk_lib_list_reserve(Arena *arena, U64 count)
{
LNK_LibList result = {0};
LNK_LibNode *nodes = push_array(arena, LNK_LibNode, count);
for (U64 i = 0; i < count; i += 1) { lnk_lib_list_push_node(&result, &nodes[i]); }
return result;
}
internal LNK_LibNodeArray
lnk_array_from_lib_list(Arena *arena, LNK_LibList list)
{
LNK_LibNodeArray result = {0};
result.v = push_array(arena, LNK_LibNode, list.count);
for (LNK_LibNode *n = list.first; n != 0; n = n->next) { result.v[result.count++] = *n; }
return result;
} }
internal B32 internal B32
@@ -169,21 +130,25 @@ THREAD_POOL_TASK_FUNC(lnk_lib_initer)
{ {
LNK_LibIniter *task = raw_task; LNK_LibIniter *task = raw_task;
LNK_LibNode *lib_node = lnk_lib_list_pop_node_atomic(&task->free_libs); U64 lib_node_idx = ins_atomic_u64_inc_eval(&task->next_free_lib_idx)-1;
LNK_LibNode *lib_node = &task->free_libs[lib_node_idx];
lib_node->data.input_idx = task_id; lib_node->data.input_idx = task_id;
B32 is_valid_lib = lnk_lib_from_data(arena, task->data_arr[task_id], task->path_arr[task_id], &lib_node->data); B32 is_valid_lib = lnk_lib_from_data(arena, task->data_arr[task_id], task->path_arr[task_id], &lib_node->data);
if (is_valid_lib) { if (is_valid_lib) {
lnk_lib_list_push_node_atomic(&task->valid_libs, lib_node); U64 valid_lib_idx = ins_atomic_u64_inc_eval(&task->valid_libs_count)-1;
task->valid_libs[valid_lib_idx] = lib_node;
} else { } else {
lnk_lib_list_push_node_atomic(&task->invalid_libs, lib_node); U64 invalid_lib_idx = ins_atomic_u64_inc_eval(&task->invalid_libs_count);
task->invalid_libs[invalid_lib_idx] = lib_node;
} }
} }
internal int internal void
lnk_lib_node_is_before(void *a, void *b) lnk_lib_list_push_node(LNK_LibList *list, LNK_LibNode *node)
{ {
return ((LNK_LibNode*)a)->data.input_idx < ((LNK_LibNode*)b)->data.input_idx; SLLQueuePush(list->first, list->last, node);
list->count += 1;
} }
internal LNK_LibNodeArray internal LNK_LibNodeArray
@@ -196,27 +161,28 @@ lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, S
// parse libs in parallel // parse libs in parallel
LNK_LibIniter task = {0}; LNK_LibIniter task = {0};
task.free_libs = lnk_lib_list_reserve(scratch.arena, lib_count); task.free_libs = push_array(arena->v[0], LNK_LibNode, lib_count);
task.valid_libs = push_array(scratch.arena, LNK_LibNode *, lib_count);
task.invalid_libs = push_array(scratch.arena, LNK_LibNode *, lib_count);
task.data_arr = data_arr.v; task.data_arr = data_arr.v;
task.path_arr = path_arr.v; task.path_arr = path_arr.v;
tp_for_parallel(tp, arena, lib_count, lnk_lib_initer, &task); tp_for_parallel(tp, arena, lib_count, lnk_lib_initer, &task);
// report invalid libs // report invalid libs
LNK_LibNodeArray invalid_libs = lnk_array_from_lib_list(scratch.arena, task.invalid_libs); radsort(task.invalid_libs, task.invalid_libs_count, lnk_lib_node_ptr_is_before);
radsort(invalid_libs.v, invalid_libs.count, lnk_lib_node_is_before); for EachIndex(i, task.invalid_libs_count) {
for (U64 i = 0; i < task.invalid_libs.count; i += 1) { U64 input_idx = task.invalid_libs[i]->data.input_idx;
U64 input_idx = invalid_libs.v[i].data.input_idx;
lnk_error(LNK_Error_InvalidLib, "%S: failed to parse library", path_arr.v[input_idx]); lnk_error(LNK_Error_InvalidLib, "%S: failed to parse library", path_arr.v[input_idx]);
} }
// push parsed libs // push parsed libs
LNK_LibNodeArray result = lnk_array_from_lib_list(arena->v[0], task.valid_libs); radsort(task.valid_libs, task.valid_libs_count, lnk_lib_node_ptr_is_before);
radsort(result.v, result.count, lnk_lib_node_is_before); for EachIndex(i, task.valid_libs_count) {
for (U64 i = result.count; i > 0; i -= 1) { lnk_lib_list_push_node(list, task.valid_libs[i]);
result.v[i-1].data.input_idx = list->count;
lnk_lib_list_push_node(list, &result.v[i-1]);
} }
LNK_LibNodeArray result = { .count = task.valid_libs_count, task.valid_libs };
scratch_end(scratch); scratch_end(scratch);
return result; return result;
} }
+22 -14
View File
@@ -25,31 +25,39 @@ typedef struct LNK_LibNode
typedef struct LNK_LibNodeArray typedef struct LNK_LibNodeArray
{ {
U64 count; U64 count;
LNK_LibNode *v; LNK_LibNode **v;
} LNK_LibNodeArray; } LNK_LibNodeArray;
typedef struct LNK_LibList typedef struct LNK_LibList
{ {
U64 count; U64 count;
struct LNK_LibNode *first; LNK_LibNode *first;
LNK_LibNode *last;
} LNK_LibList; } LNK_LibList;
// --- Workers Contexts --------------------------------------------------------
typedef struct typedef struct
{ {
String8 *data_arr; String8 *data_arr;
String8 *path_arr; String8 *path_arr;
LNK_LibList free_libs; U64 next_free_lib_idx;
LNK_LibList valid_libs; U64 valid_libs_count;
LNK_LibList invalid_libs; U64 invalid_libs_count;
LNK_LibNode *free_libs;
LNK_LibNode **valid_libs;
LNK_LibNode **invalid_libs;
} LNK_LibIniter; } LNK_LibIniter;
internal LNK_LibNode * lnk_lib_list_pop_node_atomic(LNK_LibList *list); // -----------------------------------------------------------------------------
internal void lnk_lib_list_push_node_atomic(LNK_LibList *list, LNK_LibNode *node);
internal void lnk_lib_list_push_node(LNK_LibList *list, LNK_LibNode *node); internal int lnk_lib_node_is_before(void *a, void *b);
internal LNK_LibList lnk_lib_list_reserve(Arena *arena, U64 count); internal int lnk_lib_node_ptr_is_before(void *raw_a, void *raw_b);
internal LNK_LibNodeArray lnk_array_from_lib_list(Arena *arena, LNK_LibList list);
internal B32 lnk_lib_from_data(Arena *arena, String8 data, String8 path, LNK_Lib *lib_out); internal B32 lnk_lib_from_data(Arena *arena, String8 data, String8 path, LNK_Lib *lib_out);
internal void lnk_lib_list_push_node(LNK_LibList *list, LNK_LibNode *node);
internal LNK_LibNodeArray lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, String8Array data_arr, String8Array path_arr); internal LNK_LibNodeArray lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, String8Array data_arr, String8Array path_arr);
internal B32 lnk_search_lib(LNK_Lib *lib, String8 symbol_name, U32 *member_idx_out);
+2 -2
View File
@@ -8,8 +8,8 @@ def get_sorted_objs(pdb_path):
filtered_lines = [line for line in lines if line.lstrip().startswith("Mod ")] filtered_lines = [line for line in lines if line.lstrip().startswith("Mod ")]
# sort by the obj_path portion (line format: "Mod <imod> <obj_path>") # sort by the obj_path portion (line format: "Mod <imod> <obj_path>")
def extract_path(line): return line.split(maxsplit=2)[2].lower() def extract_path(line): return line.split(maxsplit=2)[2].lower()
sorted_lines = sorted(filtered_lines, key=extract_path) #sorted_lines = sorted(filtered_lines, key=extract_path)
return sorted_lines return filtered_lines
if __name__ == "__main__": if __name__ == "__main__":
sorted_objs = get_sorted_objs(sys.argv[1]) sorted_objs = get_sorted_objs(sys.argv[1])