Skip to content

Commit fbaa28e

Browse files
committed
[MLIR][mlir-link] Fix differential with llvm-link with internal symbols
1 parent b6fcd8f commit fbaa28e

File tree

1 file changed

+60
-12
lines changed

1 file changed

+60
-12
lines changed

mlir/include/mlir/Linker/LLVMLinkerMixin.h

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)