diff options
Diffstat (limited to 'llvm/lib/Linker/IRMover.cpp')
| -rw-r--r-- | llvm/lib/Linker/IRMover.cpp | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp index 9e89cce8312e..e31faf6422ed 100644 --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -1273,14 +1273,19 @@ Error IRLinker::linkModuleFlagsMetadata() { // First build a map of the existing module flags and requirements. DenseMap<MDString *, std::pair<MDNode *, unsigned>> Flags; SmallSetVector<MDNode *, 16> Requirements; + SmallVector<unsigned, 0> Mins; + DenseSet<MDString *> SeenMin; for (unsigned I = 0, E = DstModFlags->getNumOperands(); I != E; ++I) { MDNode *Op = DstModFlags->getOperand(I); - ConstantInt *Behavior = mdconst::extract<ConstantInt>(Op->getOperand(0)); + uint64_t Behavior = + mdconst::extract<ConstantInt>(Op->getOperand(0))->getZExtValue(); MDString *ID = cast<MDString>(Op->getOperand(1)); - if (Behavior->getZExtValue() == Module::Require) { + if (Behavior == Module::Require) { Requirements.insert(cast<MDNode>(Op->getOperand(2))); } else { + if (Behavior == Module::Min) + Mins.push_back(I); Flags[ID] = std::make_pair(Op, I); } } @@ -1296,6 +1301,7 @@ Error IRLinker::linkModuleFlagsMetadata() { unsigned DstIndex; std::tie(DstOp, DstIndex) = Flags.lookup(ID); unsigned SrcBehaviorValue = SrcBehavior->getZExtValue(); + SeenMin.insert(ID); // If this is a requirement, add it and continue. if (SrcBehaviorValue == Module::Require) { @@ -1309,6 +1315,10 @@ Error IRLinker::linkModuleFlagsMetadata() { // If there is no existing flag with this ID, just add it. if (!DstOp) { + if (SrcBehaviorValue == Module::Min) { + Mins.push_back(DstModFlags->getNumOperands()); + SeenMin.erase(ID); + } Flags[ID] = std::make_pair(SrcOp, DstModFlags->getNumOperands()); DstModFlags->addOperand(SrcOp); continue; @@ -1362,8 +1372,10 @@ Error IRLinker::linkModuleFlagsMetadata() { "Expected MDTuple when appending module flags"); if (DstValue->isDistinct()) return dyn_cast<MDTuple>(DstValue); + ArrayRef<MDOperand> DstOperands = DstValue->operands(); MDTuple *New = MDTuple::getDistinct( - DstM.getContext(), SmallVector<Metadata *, 4>(DstValue->operands())); + DstM.getContext(), + SmallVector<Metadata *, 4>(DstOperands.begin(), DstOperands.end())); Metadata *FlagOps[] = {DstOp->getOperand(0), ID, New}; MDNode *Flag = MDTuple::getDistinct(DstM.getContext(), FlagOps); DstModFlags->setOperand(DstIndex, Flag); @@ -1465,6 +1477,20 @@ Error IRLinker::linkModuleFlagsMetadata() { } + // For the Min behavior, set the value to 0 if either module does not have the + // flag. + for (auto Idx : Mins) { + MDNode *Op = DstModFlags->getOperand(Idx); + MDString *ID = cast<MDString>(Op->getOperand(1)); + if (!SeenMin.count(ID)) { + ConstantInt *V = mdconst::extract<ConstantInt>(Op->getOperand(2)); + Metadata *FlagOps[] = { + Op->getOperand(0), ID, + ConstantAsMetadata::get(ConstantInt::get(V->getType(), 0))}; + DstModFlags->setOperand(Idx, MDNode::get(DstM.getContext(), FlagOps)); + } + } + // Check all of the requirements. for (unsigned I = 0, E = Requirements.size(); I != E; ++I) { MDNode *Requirement = Requirements[I]; |
