diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1624,8 +1624,10 @@ break; case Module::Min: { - Check(mdconst::dyn_extract_or_null(Op->getOperand(2)), - "invalid value for 'min' module flag (expected constant integer)", + auto *V = mdconst::dyn_extract_or_null(Op->getOperand(2)); + Check(V && V->getValue().isNonNegative(), + "invalid value for 'min' module flag (expected constant non-negative " + "integer)", Op->getOperand(2)); break; } 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 @@ -1273,14 +1273,19 @@ // First build a map of the existing module flags and requirements. DenseMap> Flags; SmallSetVector Requirements; + SmallVector Mins; + DenseSet SeenMin; for (unsigned I = 0, E = DstModFlags->getNumOperands(); I != E; ++I) { MDNode *Op = DstModFlags->getOperand(I); - ConstantInt *Behavior = mdconst::extract(Op->getOperand(0)); + uint64_t Behavior = + mdconst::extract(Op->getOperand(0))->getZExtValue(); MDString *ID = cast(Op->getOperand(1)); - if (Behavior->getZExtValue() == Module::Require) { + if (Behavior == Module::Require) { Requirements.insert(cast(Op->getOperand(2))); } else { + if (Behavior == Module::Min) + Mins.push_back(I); Flags[ID] = std::make_pair(Op, I); } } @@ -1296,6 +1301,7 @@ 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 @@ // 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; @@ -1467,6 +1477,18 @@ } + for (auto Idx : Mins) { + MDNode *Op = DstModFlags->getOperand(Idx); + MDString *ID = cast(Op->getOperand(1)); + if (!SeenMin.count(ID)) { + ConstantInt *V = mdconst::extract(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]; diff --git a/llvm/test/Linker/module-flags-min.ll b/llvm/test/Linker/module-flags-min.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Linker/module-flags-min.ll @@ -0,0 +1,27 @@ +; RUN: rm -rf %t && split-file %s %t && cd %t +; RUN: llvm-link a.ll b.ll -S -o - 2>&1 | FileCheck %s + +; CHECK: !0 = !{i32 8, !"foo", i32 2} +; CHECK-NEXT: !1 = !{i32 8, !"bar", i64 3} +; CHECK-NEXT: !2 = !{i32 8, !"only_in_a", i32 0} +; CHECK-NEXT: !3 = !{i32 8, !"required_in_b", i32 3} +; CHECK-NEXT: !4 = !{i32 8, !"only_in_b", i32 0} +; CHECK-NEXT: !5 = !{i32 3, !"require", !6} +; CHECK-NEXT: !6 = !{!"required_in_b", i32 3} + +;--- a.ll +!0 = !{ i32 8, !"foo", i32 2 } +!1 = !{ i32 8, !"bar", i64 4 } +!2 = !{ i32 8, !"only_in_a", i32 4 } +!3 = !{ i32 8, !"required_in_b", i32 3 } + +!llvm.module.flags = !{ !0, !1, !2, !3 } + +;--- b.ll +!0 = !{ i32 8, !"foo", i32 3 } +!1 = !{ i32 8, !"bar", i64 3 } +!2 = !{ i32 8, !"only_in_b", i32 3 } +!3 = !{ i32 8, !"required_in_b", i32 3 } +!4 = !{ i32 3, !"require", !{!"required_in_b", i32 3} } + +!llvm.module.flags = !{ !0, !1, !2, !3, !4 } diff --git a/llvm/test/Verifier/module-flags-1.ll b/llvm/test/Verifier/module-flags-1.ll --- a/llvm/test/Verifier/module-flags-1.ll +++ b/llvm/test/Verifier/module-flags-1.ll @@ -46,8 +46,10 @@ !19 = !{i32 7, !"max", !"max"} ; Check that any 'min' module flags are valid. -; CHECK: invalid value for 'min' module flag (expected constant integer) +; CHECK: invalid value for 'min' module flag (expected constant non-negative integer) !20 = !{i32 8, !"min", !"min"} +; CHECK: invalid value for 'min' module flag (expected constant non-negative integer) +!21 = !{i32 8, !"min", i32 -1} ; Check that any 'require' module flags are valid. ; CHECK: invalid requirement on flag, flag is not present in module @@ -62,4 +64,4 @@ !llvm.module.flags = !{ !0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, - !16, !17, !18, !19, !20 } + !16, !17, !18, !19, !20, !21 }