summaryrefslogtreecommitdiff
path: root/llvm/lib/Linker/IRMover.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Linker/IRMover.cpp')
-rw-r--r--llvm/lib/Linker/IRMover.cpp32
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];