symresolve.c (1743B)
1 #include "obj/symresolve.h" 2 3 SymMergeResult symresolve_merge(SymAttrs existing, SymAttrs incoming) { 4 SymMergeResult r; 5 int new_strength = symresolve_bind_strength(incoming.bind); 6 int old_strength = symresolve_bind_strength(existing.bind); 7 r.kind = SYM_MERGE_KEEP_EXISTING; 8 r.merged_align = 0; 9 10 if (existing.kind == SK_COMMON && incoming.kind == SK_COMMON) { 11 /* Tentative-definition merge: the larger reservation wins, alignment is the 12 * max of both. A smaller-or-equal incoming common changes nothing (this 13 * matches the linker's prior behavior, which did not bump alignment when 14 * the size did not grow). */ 15 if (incoming.size > existing.size) { 16 r.kind = SYM_MERGE_COMMON; 17 r.merged_align = (incoming.common_align > existing.common_align) 18 ? incoming.common_align 19 : existing.common_align; 20 } 21 } else if (incoming.kind == SK_COMMON) { 22 /* A real definition already present beats an incoming common. */ 23 } else if (existing.kind == SK_COMMON) { 24 /* A real definition beats a previously-seen common. */ 25 r.kind = SYM_MERGE_REPLACE; 26 } else if (new_strength > old_strength) { 27 r.kind = SYM_MERGE_REPLACE; 28 } else if (new_strength == old_strength && 29 new_strength == symresolve_bind_strength(SB_GLOBAL)) { 30 /* Two strong definitions: legal only as COFF SELECTANY when both sit in 31 * COMDAT sections (keep the first, discard the new); otherwise ODR. */ 32 r.kind = (existing.in_comdat && incoming.in_comdat) ? SYM_MERGE_COMDAT_DISCARD 33 : SYM_MERGE_ODR_ERROR; 34 } 35 /* else: incoming is weaker (or weak-vs-weak); keep the first definition. */ 36 return r; 37 }