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;
for (U64 i = i_begin; i < i_end; i += 1) {
LNK_Symbol *symbol = c->v[i].symbol;
LNK_ObjSymbolRef symbol_ref = lnk_ref_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);
LNK_SymbolSearchType search_type = lnk_search_type_from_symbol(symbol);
if (symbol_interp == COFF_SymbolValueInterp_Undefined) {
if (search_type == LNK_SymbolSearch_Undefined || search_type == LNK_SymbolSearch_WeakLibrary) {
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 (symbol_interp == COFF_SymbolValueInterp_Weak) {
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol_parsed, symbol_ref.obj->header.is_big_obj);
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) {
} else if (search_type == LNK_SymbolSearch_WeakAntiDependency && search_anti_deps) {
LNK_ObjSymbolRef symbol_ref = lnk_ref_from_symbol(symbol);
LNK_ObjSymbolRef dep_symbol = {0};
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);
@@ -1734,8 +1725,6 @@ THREAD_POOL_TASK_FUNC(lnk_search_lib_task)
}
}
}
}
}
// cache search cursors
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.
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
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)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol);
LNK_SymbolSearchType search_type = lnk_symbol_search_type_from_coff(obj, symbol, interp);
switch (interp) {
case COFF_SymbolValueInterp_Regular: {
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) {
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);
}
} break;
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);
} break;
case COFF_SymbolValueInterp_Undefined: {
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);
}
} break;
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);
} break;
case COFF_SymbolValueInterp_Abs: {
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);
}
} break;
+56 -6
View File
@@ -1,8 +1,27 @@
// Copyright (c) Epic Games Tools
// 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 *
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);
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);
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;
}
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
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
src->last_ref->next = dst->first_ref;
src->last_ref = dst->last_ref;
lnk_last_ref_from_symbol(src)->next = dst->first_ref;
lnk_symbol_set_last_ref(src, lnk_last_ref_from_symbol(dst));
// assert leader section is live
#if BUILD_DEBUG
@@ -562,9 +610,9 @@ internal void
lnk_symbol_table_push_(LNK_SymbolTable *symtab, Arena *arena, U64 worker_id, LNK_Symbol *symbol)
{
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;
if (interp == COFF_SymbolValueInterp_Weak || interp == COFF_SymbolValueInterp_Undefined) {
if (search_type != LNK_SymbolSearch_Null) {
chunks = &symtab->search_chunks[worker_id];
} else {
chunks = &symtab->chunks[worker_id];
@@ -790,8 +838,10 @@ THREAD_POOL_TASK_FUNC(lnk_replace_weak_with_default_symbol_task)
symbol16->value = 0;
symbol16->storage_class = COFF_SymStorageClass_External;
}
lnk_symbol_set_search_type(symbol, LNK_SymbolSearch_Undefined);
} else {
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_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
{
String8 name;
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;
StaticAssert(sizeof(LNK_Symbol) == 32, lnk_symbol_size_check);
// --- Symbol Containers -------------------------------------------------------
typedef struct LNK_SymbolNode
@@ -89,7 +101,12 @@ typedef struct
// --- 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_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 void lnk_replace_weak_with_default_symbols(TP_Context *tp, LNK_SymbolTable *symtab);