diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -1260,15 +1260,52 @@ Flags[ID].first = SrcOp; }; + // Check the input bitcode is swift generated bitcode. + auto isSwiftBitCode = [&](Module &M) { + SmallVector ModuleFlags; + M.getModuleFlagsMetadata(ModuleFlags); + for (const auto &MFE: ModuleFlags) { + if (MFE.Behavior == Module::Require) + continue; + StringRef Key = MFE.Key->getString(); + if (Key == "Swift Version") + return true; + } + return false; + }; + // If either flag has override behavior, handle it first. if (DstBehaviorValue == Module::Override) { // Diagnose inconsistent flags which both have override behavior. if (SrcBehaviorValue == Module::Override && - SrcOp->getOperand(2) != DstOp->getOperand(2)) + SrcOp->getOperand(2) != DstOp->getOperand(2)) { + if (ID->getString().equals("Objective-C Garbage Collection")) { + + // Merge the value of metadata "Objective-C Garbage Collection" + // into one value by shifting. The purpose of this change is + // to support LTO in Swift and Objective-C mixed project. + + auto Int32Ty = Type::getInt32Ty(DstM.getContext()); + auto SrcMD = dyn_cast(SrcOp->getOperand(2)); + auto DstMD = dyn_cast(DstOp->getOperand(2)); + assert(!SrcMD && !DstMD); + unsigned SrcVal = SrcMD->getValue()->getUniqueInteger().getZExtValue(); + unsigned DstVal = DstMD->getValue()->getUniqueInteger().getZExtValue(); + if ((isSwiftBitCode(*SrcM) && DstVal < 64) || + (isSwiftBitCode(DstM) && SrcVal < 64)) { + unsigned resVal = SrcVal | DstVal; + SrcOp->replaceOperandWith(2, + ConstantAsMetadata::get(ConstantInt::get(Int32Ty,resVal))); + DstOp->replaceOperandWith(2, + ConstantAsMetadata::get(ConstantInt::get(Int32Ty,resVal))); + continue; + } + } return stringErr("linking module flags '" + ID->getString() + "': IDs have conflicting override values in '" + SrcM->getModuleIdentifier() + "' and '" + DstM.getModuleIdentifier() + "'"); + } continue; } else if (SrcBehaviorValue == Module::Override) { // Update the destination flag to that of the source.