@@ -266,22 +266,27 @@ class LLVMLinkerMixin {
266266 Linkage srcLinkage = derived.getLinkage (pair.src );
267267 Linkage dstLinkage = derived.getLinkage (pair.dst );
268268
269- Visibility srcVisibility = derived.getVisibility (pair.src );
270- Visibility dstVisibility = derived.getVisibility (pair.dst );
271- Visibility visibility = getMinVisibility (srcVisibility, dstVisibility);
269+ const bool srcIsDeclaration = isDeclarationForLinker (pair.src );
270+ const bool dstIsDeclaration = isDeclarationForLinker (pair.dst );
272271
273- derived.setVisibility (pair.src , visibility);
274- derived.setVisibility (pair.dst , visibility);
272+ // Only unify visibility and unnamed_addr for non-local, non-appending linkage.
273+ // LLVM requires: local linkage must have default visibility.
274+ // Unifying visibility before checking linkage can violate this invariant.
275+ if (!isLocalLinkage (srcLinkage) && !isAppendingLinkage (srcLinkage)) {
276+ Visibility srcVisibility = derived.getVisibility (pair.src );
277+ Visibility dstVisibility = derived.getVisibility (pair.dst );
278+ Visibility visibility = getMinVisibility (srcVisibility, dstVisibility);
275279
276- UnnamedAddr srcUnnamedAddr = derived.getUnnamedAddr (pair.src );
277- UnnamedAddr dstUnnamedAddr = derived.getUnnamedAddr (pair.dst );
280+ derived.setVisibility (pair.src , visibility );
281+ derived.setVisibility (pair.dst , visibility );
278282
279- UnnamedAddr unnamedAddr = getMinUnnamedAddr (srcUnnamedAddr, dstUnnamedAddr);
280- derived.setUnnamedAddr (pair.src , unnamedAddr);
281- derived.setUnnamedAddr (pair.dst , unnamedAddr);
283+ UnnamedAddr srcUnnamedAddr = derived.getUnnamedAddr (pair.src );
284+ UnnamedAddr dstUnnamedAddr = derived.getUnnamedAddr (pair.dst );
282285
283- const bool srcIsDeclaration = isDeclarationForLinker (pair.src );
284- const bool dstIsDeclaration = isDeclarationForLinker (pair.dst );
286+ UnnamedAddr unnamedAddr = getMinUnnamedAddr (srcUnnamedAddr, dstUnnamedAddr);
287+ derived.setUnnamedAddr (pair.src , unnamedAddr);
288+ derived.setUnnamedAddr (pair.dst , unnamedAddr);
289+ }
285290
286291 if (!isLocalLinkage (srcLinkage) && !isAppendingLinkage (srcLinkage)) {
287292 if (derived.isGlobalVar (pair.src ) && derived.isGlobalVar (pair.dst )) {
@@ -437,6 +442,49 @@ class SymbolAttrLLVMLinkerInterface
437442 return LinkerMixin::getConflictResolution (pair);
438443 }
439444
445+ Conflict findConflict (Operation *src,
446+ SymbolTableCollection &collection) const override {
447+ assert (canBeLinked (src) && " expected linkable operation" );
448+ const DerivedLinkerInterface &derived = LinkerMixin::getDerived ();
449+
450+ // If the source has local linkage, there is no name match-up going on.
451+ // This matches LLVM's behavior where local linkage symbols never conflict.
452+ if (isLocalLinkage (derived.getLinkage (src)))
453+ return Conflict::noConflict (src);
454+
455+ // Check for conflict in the summary
456+ StringRef symbol = getSymbol (src);
457+ std::lock_guard<std::mutex> lock (this ->summaryMutex );
458+ auto it = this ->summary .find (symbol);
459+ if (it == this ->summary .end ())
460+ return Conflict::noConflict (src);
461+
462+ // If we found a global with the same name, but it has local linkage,
463+ // we are really not doing any linkage here.
464+ if (isLocalLinkage (derived.getLinkage (it->second )))
465+ return Conflict::noConflict (src);
466+
467+ return {it->second , src};
468+ }
469+
470+ void registerForLink (Operation *op,
471+ SymbolTableCollection &collection) override {
472+ assert (canBeLinked (op) && " expected linkable operation" );
473+
474+ std::lock_guard<std::mutex> lock (this ->summaryMutex );
475+
476+ // Local linkage symbols are module-private and should not participate
477+ // in conflict detection. Instead of adding them to the summary (which
478+ // is used for conflict detection), add them to the uniqued set so they
479+ // get materialized with unique names if needed. This matches LLVM's
480+ // behavior where local linkage symbols are copied independently.
481+ if (isLocalLinkage (LinkerMixin::getDerived ().getLinkage (op))) {
482+ this ->uniqued .insert (op);
483+ } else {
484+ this ->summary [getSymbol (op)] = op;
485+ }
486+ }
487+
440488 LogicalResult resolveConflict (Conflict pair,
441489 ConflictResolution resolution,
442490 SymbolTableCollection &collection) override {
0 commit comments