@@ -108,6 +108,13 @@ LLVM::LLVMSymbolLinkerInterface::getComdatSelector(Operation *op) {
108108 return {{comdatSelector.getSymName (), comdatSelector.getComdat ()}};
109109}
110110
111+ LLVM::comdat::Comdat
112+ LLVM::LLVMSymbolLinkerInterface::getComdatSelectionKind (Operation *op) {
113+ if (auto selector = dyn_cast<LLVM::ComdatSelectorOp>(op))
114+ return selector.getComdat ();
115+ llvm_unreachable (" expected selector op" );
116+ }
117+
111118// Return true if the primary definition of this global value is outside of
112119// the current translation unit.
113120bool LLVM::LLVMSymbolLinkerInterface::isDeclaration (Operation *op) {
@@ -547,6 +554,80 @@ Operation *LLVM::LLVMSymbolLinkerInterface::appendGlobals(llvm::StringRef glob,
547554 llvm_unreachable (" unexpected operation" );
548555}
549556
557+ static ConflictResolution computeComdatResolution () {}
558+
559+ LogicalResult LLVM::LLVMSymbolLinkerInterface::resolveComdats (
560+ ModuleOp srcMod, SymbolTableCollection &collection) {
561+ LLVM::ComdatOp srcComdatOp;
562+ LLVM::ComdatOp dstComdatOp;
563+ for (auto &op : srcMod) {
564+ if (auto comdatOp = dyn_cast<LLVM::ComdatOp>(op)) {
565+ srcComdatOp = comdatOp;
566+ break ;
567+ }
568+ }
569+
570+ SymbolUserMap srcSymbolUsers (collection,
571+ srcComdatOp->getParentOfType <ModuleOp>());
572+ // Get current resolved ComdatOp or insert srcComdatOp into summary
573+ // TODO: use comdat summary to find conflict
574+ if (auto it = summary.find (getSymbol (srcComdatOp)); it != summary.end ()) {
575+ dstComdatOp = cast<LLVM::ComdatOp>(*it);
576+ } else {
577+ summary[getSymbol (srcComdatOp)] = srcComdatOp;
578+ for (Operation &op : srcComdatOp.getBody ().front ()) {
579+ ArrayRef<Operation *> users = srcSymbolUsers.getUsers (&op);
580+ comdatResolution.try_emplace (
581+ getSymbol (&op),
582+ std::make_pair (link::Comdat{getComdatSelectionKind (&op),
583+ &op,
584+ {users.begin (), users.end ()}},
585+ ConflictResolution::LinkFromSrc));
586+ }
587+ return success ();
588+ }
589+
590+ for (Operation &op : srcComdatOp.getBody ().front ()) {
591+ auto srcSelector = cast<LLVM::ComdatSelectorOp>(op);
592+ // TODO: use custom enum for comdat?
593+ // If no conflict choose src
594+ auto res = ConflictResolution::LinkFromSrc;
595+ if (auto dstComdatIt = comdatResolution.find (getSymbol (&op));
596+ dstComdatIt != comdatResolution.end ()) {
597+ res = computeComdatResolution (/* TODO*/ );
598+ // remove dst ops from summary if src selected
599+ }
600+ switch (res) {
601+ case ConflictResolution::LinkFromSrc: {
602+ ArrayRef<Operation *> users = srcSymbolUsers.getUsers (&op);
603+ comdatResolution.try_emplace (
604+ getSymbol (srcSelector),
605+ std::make_pair (link::Comdat{getComdatSelectionKind (srcSelector),
606+ srcSelector,
607+ {users.begin (), users.end ()}},
608+ ConflictResolution::LinkFromSrc));
609+ break ;
610+ }
611+ case ConflictResolution::LinkFromDst:
612+ case ConflictResolution::LinkFromBothAndRenameDst:
613+ case ConflictResolution::LinkFromBothAndRenameSrc:
614+ case ConflictResolution::Failure:
615+ return failure ();
616+ }
617+ }
618+ return success ();
619+ }
620+
621+ std::optional<link::ConflictResolution>
622+ LLVM::LLVMSymbolLinkerInterface::getComdatResolution (Operation *op) {
623+ if (hasComdat (op)) {
624+ if (auto resIt = comdatResolution.find (getSymbol (op));
625+ resIt != comdatResolution.end ())
626+ return resIt->second .second ;
627+ }
628+ return {};
629+ }
630+
550631// ===----------------------------------------------------------------------===//
551632// registerLinkerInterface
552633// ===----------------------------------------------------------------------===//
0 commit comments