WIP cache COFF symbol interp

This commit is contained in:
Nikita Smith
2026-07-27 14:47:23 -07:00
committed by Ryan Fleury
parent a779d3f1a5
commit 4cc0f4813b
4 changed files with 98 additions and 42 deletions
+5 -16
View File
@@ -1702,24 +1702,15 @@ THREAD_POOL_TASK_FUNC(lnk_search_lib_task)
U64 i_end = (c == end_chunk) ? end_count : c->count; U64 i_end = (c == end_chunk) ? end_count : c->count;
for (U64 i = i_begin; i < i_end; i += 1) { for (U64 i = i_begin; i < i_end; i += 1) {
LNK_Symbol *symbol = c->v[i].symbol; LNK_Symbol *symbol = c->v[i].symbol;
LNK_ObjSymbolRef symbol_ref = lnk_ref_from_symbol(symbol); LNK_SymbolSearchType search_type = lnk_search_type_from_symbol(symbol);
COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_coff_symbol_idx_no_name(symbol_ref.obj, symbol_ref.symbol_idx);
COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed);
if (symbol_interp == COFF_SymbolValueInterp_Undefined) { if (search_type == LNK_SymbolSearch_Undefined || search_type == LNK_SymbolSearch_WeakLibrary) {
U32 member_idx; U32 member_idx;
if (lnk_search_lib(lib, symbol->name, &member_idx)) { if (lnk_search_lib(lib, symbol->name, &member_idx)) {
lnk_queue_lib_member(arena, task->imports_hm, task->link->lib_member_infos_hm, member_ref_list, symbol, lib, lib_member_infos, member_idx); lnk_queue_lib_member(arena, task->imports_hm, task->link->lib_member_infos_hm, member_ref_list, symbol, lib, lib_member_infos, member_idx);
} }
} else if (symbol_interp == COFF_SymbolValueInterp_Weak) { } else if (search_type == LNK_SymbolSearch_WeakAntiDependency && search_anti_deps) {
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol_parsed, symbol_ref.obj->header.is_big_obj); LNK_ObjSymbolRef symbol_ref = lnk_ref_from_symbol(symbol);
if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) {
U32 member_idx;
if (lnk_search_lib(lib, symbol->name, &member_idx)) {
lnk_queue_lib_member(arena, task->imports_hm, task->link->lib_member_infos_hm, member_ref_list, symbol, lib, lib_member_infos, member_idx);
}
} else if (weak_ext->characteristics == COFF_WeakExt_AntiDependency) {
if (search_anti_deps) {
LNK_ObjSymbolRef dep_symbol = {0}; LNK_ObjSymbolRef dep_symbol = {0};
if (lnk_resolve_weak_symbol(symtab, symbol_ref, &dep_symbol)) { if (lnk_resolve_weak_symbol(symtab, symbol_ref, &dep_symbol)) {
COFF_ParsedSymbol dep_parsed = lnk_parsed_symbol_from_coff_symbol_idx_no_name(dep_symbol.obj, dep_symbol.symbol_idx); COFF_ParsedSymbol dep_parsed = lnk_parsed_symbol_from_coff_symbol_idx_no_name(dep_symbol.obj, dep_symbol.symbol_idx);
@@ -1734,8 +1725,6 @@ THREAD_POOL_TASK_FUNC(lnk_search_lib_task)
} }
} }
} }
}
}
// cache search cursors // cache search cursors
lib->search_cursor_chunks[task_id] = end_chunk; lib->search_cursor_chunks[task_id] = end_chunk;
@@ -1979,7 +1968,7 @@ lnk_link_inputs(TP_Context *tp,
// replace the import symbol with a stub, which is later replaced with the real import symbol once import obj is ready. // replace the import symbol with a stub, which is later replaced with the real import symbol once import obj is ready.
member_ref->link_symbol->first_ref = import_stub->first_ref; member_ref->link_symbol->first_ref = import_stub->first_ref;
member_ref->link_symbol->last_ref = import_stub->last_ref; member_ref->link_symbol->last_ref_and_search_type = import_stub->last_ref_and_search_type;
// push import member for import obj generation // push import member for import obj generation
lnk_lib_member_ref_list_push_node(&link->imports, member_ref); lnk_lib_member_ref_list_push_node(&link->imports, member_ref);
+6 -5
View File
@@ -457,6 +457,7 @@ THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table)
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol); COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol);
LNK_SymbolSearchType search_type = lnk_symbol_search_type_from_coff(obj, symbol, interp);
switch (interp) { switch (interp) {
case COFF_SymbolValueInterp_Regular: { case COFF_SymbolValueInterp_Regular: {
if (symbol.storage_class == COFF_SymStorageClass_External) { if (symbol.storage_class == COFF_SymStorageClass_External) {
@@ -464,27 +465,27 @@ THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table)
if (*section.flags & COFF_SectionFlag_LnkRemove) { if (*section.flags & COFF_SectionFlag_LnkRemove) {
break; break;
} }
LNK_Symbol *defn = lnk_make_symbol(arena, lnk_symbol_name_from_coff_symbol_idx(obj, symbol_idx), obj, symbol_idx); LNK_Symbol *defn = lnk_make_symbol(arena, lnk_symbol_name_from_coff_symbol_idx(obj, symbol_idx), obj, symbol_idx, search_type);
lnk_symbol_table_push_(task->symtab, arena, worker_id, defn); lnk_symbol_table_push_(task->symtab, arena, worker_id, defn);
} }
} break; } break;
case COFF_SymbolValueInterp_Weak: { case COFF_SymbolValueInterp_Weak: {
LNK_Symbol *defn = lnk_make_symbol(arena, lnk_symbol_name_from_coff_symbol_idx(obj, symbol_idx), obj, symbol_idx); LNK_Symbol *defn = lnk_make_symbol(arena, lnk_symbol_name_from_coff_symbol_idx(obj, symbol_idx), obj, symbol_idx, search_type);
lnk_symbol_table_push_(task->symtab, arena, worker_id, defn); lnk_symbol_table_push_(task->symtab, arena, worker_id, defn);
} break; } break;
case COFF_SymbolValueInterp_Undefined: { case COFF_SymbolValueInterp_Undefined: {
if (symbol.storage_class == COFF_SymStorageClass_External) { if (symbol.storage_class == COFF_SymStorageClass_External) {
LNK_Symbol *defn = lnk_make_symbol(arena, lnk_symbol_name_from_coff_symbol_idx(obj, symbol_idx), obj, symbol_idx); LNK_Symbol *defn = lnk_make_symbol(arena, lnk_symbol_name_from_coff_symbol_idx(obj, symbol_idx), obj, symbol_idx, search_type);
lnk_symbol_table_push_(task->symtab, arena, worker_id, defn); lnk_symbol_table_push_(task->symtab, arena, worker_id, defn);
} }
} break; } break;
case COFF_SymbolValueInterp_Common: { case COFF_SymbolValueInterp_Common: {
LNK_Symbol *defn = lnk_make_symbol(arena, lnk_symbol_name_from_coff_symbol_idx(obj, symbol_idx), obj, symbol_idx); LNK_Symbol *defn = lnk_make_symbol(arena, lnk_symbol_name_from_coff_symbol_idx(obj, symbol_idx), obj, symbol_idx, search_type);
lnk_symbol_table_push_(task->symtab, arena, worker_id, defn); lnk_symbol_table_push_(task->symtab, arena, worker_id, defn);
} break; } break;
case COFF_SymbolValueInterp_Abs: { case COFF_SymbolValueInterp_Abs: {
if (symbol.storage_class == COFF_SymStorageClass_External) { if (symbol.storage_class == COFF_SymStorageClass_External) {
LNK_Symbol *defn = lnk_make_symbol(arena, lnk_symbol_name_from_coff_symbol_idx(obj, symbol_idx), obj, symbol_idx); LNK_Symbol *defn = lnk_make_symbol(arena, lnk_symbol_name_from_coff_symbol_idx(obj, symbol_idx), obj, symbol_idx, search_type);
lnk_symbol_table_push_(task->symtab, arena, worker_id, defn); lnk_symbol_table_push_(task->symtab, arena, worker_id, defn);
} }
} break; } break;
+56 -6
View File
@@ -1,8 +1,27 @@
// Copyright (c) Epic Games Tools // Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
#define LNK_SYMBOL_SEARCH_TYPE_MASK 7ull
internal LNK_SymbolSearchType
lnk_symbol_search_type_from_coff(LNK_Obj *obj, COFF_ParsedSymbol symbol, COFF_SymbolValueInterpType interp)
{
LNK_SymbolSearchType search_type = LNK_SymbolSearch_Null;
if (interp == COFF_SymbolValueInterp_Undefined) {
search_type = LNK_SymbolSearch_Undefined;
} else if (interp == COFF_SymbolValueInterp_Weak) {
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol, obj->header.is_big_obj);
switch (weak_ext->characteristics) {
case COFF_WeakExt_SearchLibrary: search_type = LNK_SymbolSearch_WeakLibrary; break;
case COFF_WeakExt_AntiDependency: search_type = LNK_SymbolSearch_WeakAntiDependency; break;
default: search_type = LNK_SymbolSearch_WeakOther; break;
}
}
return search_type;
}
internal LNK_Symbol * internal LNK_Symbol *
lnk_make_symbol(Arena *arena, String8 name, LNK_Obj *obj, U32 symbol_idx) lnk_make_symbol(Arena *arena, String8 name, LNK_Obj *obj, U32 symbol_idx, LNK_SymbolSearchType search_type)
{ {
LNK_ObjSymbolRefNode *ref = push_array(arena, LNK_ObjSymbolRefNode, 1); LNK_ObjSymbolRefNode *ref = push_array(arena, LNK_ObjSymbolRefNode, 1);
ref->v.obj = obj; ref->v.obj = obj;
@@ -10,11 +29,40 @@ lnk_make_symbol(Arena *arena, String8 name, LNK_Obj *obj, U32 symbol_idx)
LNK_Symbol *symbol = push_array(arena, LNK_Symbol, 1); LNK_Symbol *symbol = push_array(arena, LNK_Symbol, 1);
symbol->name = name; symbol->name = name;
SLLQueuePush(symbol->first_ref, symbol->last_ref, ref); symbol->first_ref = ref;
Assert((IntFromPtr(ref) & LNK_SYMBOL_SEARCH_TYPE_MASK) == 0);
Assert(search_type <= LNK_SymbolSearch_WeakOther);
symbol->last_ref_and_search_type = IntFromPtr(ref) | search_type;
return symbol; return symbol;
} }
internal LNK_ObjSymbolRefNode *
lnk_last_ref_from_symbol(LNK_Symbol *symbol)
{
return PtrFromInt(symbol->last_ref_and_search_type & ~LNK_SYMBOL_SEARCH_TYPE_MASK);
}
internal LNK_SymbolSearchType
lnk_search_type_from_symbol(LNK_Symbol *symbol)
{
return safe_cast_u32(symbol->last_ref_and_search_type & LNK_SYMBOL_SEARCH_TYPE_MASK);
}
internal void
lnk_symbol_set_last_ref(LNK_Symbol *symbol, LNK_ObjSymbolRefNode *last_ref)
{
Assert((IntFromPtr(last_ref) & LNK_SYMBOL_SEARCH_TYPE_MASK) == 0);
symbol->last_ref_and_search_type = IntFromPtr(last_ref) | lnk_search_type_from_symbol(symbol);
}
internal void
lnk_symbol_set_search_type(LNK_Symbol *symbol, LNK_SymbolSearchType search_type)
{
Assert(search_type <= LNK_SymbolSearch_WeakOther);
symbol->last_ref_and_search_type = (symbol->last_ref_and_search_type & ~LNK_SYMBOL_SEARCH_TYPE_MASK) | search_type;
}
internal int internal int
lnk_obj_symbol_ref_is_before(void *raw_a, void *raw_b) lnk_obj_symbol_ref_is_before(void *raw_a, void *raw_b)
{ {
@@ -357,8 +405,8 @@ lnk_on_symbol_replace(LNK_Symbol *dst, LNK_Symbol *src)
} }
// merge symbol refs // merge symbol refs
src->last_ref->next = dst->first_ref; lnk_last_ref_from_symbol(src)->next = dst->first_ref;
src->last_ref = dst->last_ref; lnk_symbol_set_last_ref(src, lnk_last_ref_from_symbol(dst));
// assert leader section is live // assert leader section is live
#if BUILD_DEBUG #if BUILD_DEBUG
@@ -562,9 +610,9 @@ internal void
lnk_symbol_table_push_(LNK_SymbolTable *symtab, Arena *arena, U64 worker_id, LNK_Symbol *symbol) lnk_symbol_table_push_(LNK_SymbolTable *symtab, Arena *arena, U64 worker_id, LNK_Symbol *symbol)
{ {
U64 hash = lnk_symbol_table_hasher(symbol->name); U64 hash = lnk_symbol_table_hasher(symbol->name);
COFF_SymbolValueInterpType interp = lnk_interp_from_symbol(symbol); LNK_SymbolSearchType search_type = lnk_search_type_from_symbol(symbol);
LNK_SymbolHashTrieChunkList *chunks; LNK_SymbolHashTrieChunkList *chunks;
if (interp == COFF_SymbolValueInterp_Weak || interp == COFF_SymbolValueInterp_Undefined) { if (search_type != LNK_SymbolSearch_Null) {
chunks = &symtab->search_chunks[worker_id]; chunks = &symtab->search_chunks[worker_id];
} else { } else {
chunks = &symtab->chunks[worker_id]; chunks = &symtab->chunks[worker_id];
@@ -790,8 +838,10 @@ THREAD_POOL_TASK_FUNC(lnk_replace_weak_with_default_symbol_task)
symbol16->value = 0; symbol16->value = 0;
symbol16->storage_class = COFF_SymStorageClass_External; symbol16->storage_class = COFF_SymStorageClass_External;
} }
lnk_symbol_set_search_type(symbol, LNK_SymbolSearch_Undefined);
} else { } else {
symbol->first_ref->v = resolve; symbol->first_ref->v = resolve;
lnk_symbol_set_search_type(symbol, LNK_SymbolSearch_Null);
} }
} }
} }
+19 -3
View File
@@ -17,13 +17,25 @@ typedef struct LNK_ObjSymbolRefNode
LNK_ObjSymbolRef v; LNK_ObjSymbolRef v;
} LNK_ObjSymbolRefNode; } LNK_ObjSymbolRefNode;
typedef U32 LNK_SymbolSearchType;
enum
{
LNK_SymbolSearch_Null,
LNK_SymbolSearch_Undefined,
LNK_SymbolSearch_WeakLibrary,
LNK_SymbolSearch_WeakAntiDependency,
LNK_SymbolSearch_WeakOther,
};
typedef struct LNK_Symbol typedef struct LNK_Symbol
{ {
String8 name; String8 name;
LNK_ObjSymbolRefNode *first_ref; LNK_ObjSymbolRefNode *first_ref;
LNK_ObjSymbolRefNode *last_ref; U64 last_ref_and_search_type; // Tail pointer with search type in its low bits.
} LNK_Symbol; } LNK_Symbol;
StaticAssert(sizeof(LNK_Symbol) == 32, lnk_symbol_size_check);
// --- Symbol Containers ------------------------------------------------------- // --- Symbol Containers -------------------------------------------------------
typedef struct LNK_SymbolNode typedef struct LNK_SymbolNode
@@ -89,7 +101,12 @@ typedef struct
// --- Symbol ----------------------------------------------------------------- // --- Symbol -----------------------------------------------------------------
internal LNK_Symbol * lnk_make_symbol(Arena *arena, String8 name, struct LNK_Obj *obj, U32 symbol_idx); internal LNK_SymbolSearchType lnk_symbol_search_type_from_coff(struct LNK_Obj *obj, COFF_ParsedSymbol symbol, COFF_SymbolValueInterpType interp);
internal LNK_Symbol * lnk_make_symbol(Arena *arena, String8 name, struct LNK_Obj *obj, U32 symbol_idx, LNK_SymbolSearchType search_type);
internal LNK_ObjSymbolRefNode * lnk_last_ref_from_symbol(LNK_Symbol *symbol);
internal LNK_SymbolSearchType lnk_search_type_from_symbol(LNK_Symbol *symbol);
internal void lnk_symbol_set_last_ref(LNK_Symbol *symbol, LNK_ObjSymbolRefNode *last_ref);
internal void lnk_symbol_set_search_type(LNK_Symbol *symbol, LNK_SymbolSearchType search_type);
internal int lnk_obj_symbol_ref_is_before(void *raw_a, void *raw_b); internal int lnk_obj_symbol_ref_is_before(void *raw_a, void *raw_b);
internal int lnk_obj_symbol_ref_ptr_is_before(void *raw_a, void *raw_b); internal int lnk_obj_symbol_ref_ptr_is_before(void *raw_a, void *raw_b);
@@ -138,4 +155,3 @@ internal B32 lnk_resolve_weak_symbol(LNK_SymbolTable *symtab, LNK_ObjSymbolRef s
internal B32 lnk_resolve_symbol(LNK_SymbolTable *symtab, LNK_ObjSymbolRef symbol, LNK_ObjSymbolRef *symbol_out); internal B32 lnk_resolve_symbol(LNK_SymbolTable *symtab, LNK_ObjSymbolRef symbol, LNK_ObjSymbolRef *symbol_out);
internal void lnk_replace_weak_with_default_symbols(TP_Context *tp, LNK_SymbolTable *symtab); internal void lnk_replace_weak_with_default_symbols(TP_Context *tp, LNK_SymbolTable *symtab);