Index: llvm/trunk/include/llvm/IR/Module.h =================================================================== --- llvm/trunk/include/llvm/IR/Module.h +++ llvm/trunk/include/llvm/IR/Module.h @@ -139,9 +139,12 @@ /// during the append operation. AppendUnique = 6, + /// Takes the max of the two values, which are required to be integers. + Max = 7, + // Markers: ModFlagBehaviorFirstVal = Error, - ModFlagBehaviorLastVal = AppendUnique + ModFlagBehaviorLastVal = Max }; /// Checks if Metadata represents a valid ModFlagBehavior, and stores the Index: llvm/trunk/lib/IR/Module.cpp =================================================================== --- llvm/trunk/lib/IR/Module.cpp +++ llvm/trunk/lib/IR/Module.cpp @@ -481,7 +481,7 @@ } void Module::setPICLevel(PICLevel::Level PL) { - addModuleFlag(ModFlagBehavior::Error, "PIC Level", PL); + addModuleFlag(ModFlagBehavior::Max, "PIC Level", PL); } PIELevel::Level Module::getPIELevel() const { @@ -495,7 +495,7 @@ } void Module::setPIELevel(PIELevel::Level PL) { - addModuleFlag(ModFlagBehavior::Error, "PIE Level", PL); + addModuleFlag(ModFlagBehavior::Max, "PIE Level", PL); } void Module::setProfileSummary(Metadata *M) { Index: llvm/trunk/lib/IR/Verifier.cpp =================================================================== --- llvm/trunk/lib/IR/Verifier.cpp +++ llvm/trunk/lib/IR/Verifier.cpp @@ -1282,6 +1282,13 @@ // These behavior types accept any value. break; + case Module::Max: { + Assert(mdconst::dyn_extract_or_null(Op->getOperand(2)), + "invalid value for 'max' module flag (expected constant integer)", + Op->getOperand(2)); + break; + } + case Module::Require: { // The value should itself be an MDNode with two operands, a flag ID (an // MDString), and a value. Index: llvm/trunk/lib/Linker/IRMover.cpp =================================================================== --- llvm/trunk/lib/Linker/IRMover.cpp +++ llvm/trunk/lib/Linker/IRMover.cpp @@ -1157,6 +1157,11 @@ mdconst::extract(DstOp->getOperand(0)); unsigned DstBehaviorValue = DstBehavior->getZExtValue(); + auto overrideDstValue = [&]() { + DstModFlags->setOperand(DstIndex, SrcOp); + Flags[ID].first = SrcOp; + }; + // If either flag has override behavior, handle it first. if (DstBehaviorValue == Module::Override) { // Diagnose inconsistent flags which both have override behavior. @@ -1167,8 +1172,7 @@ continue; } else if (SrcBehaviorValue == Module::Override) { // Update the destination flag to that of the source. - DstModFlags->setOperand(DstIndex, SrcOp); - Flags[ID].first = SrcOp; + overrideDstValue(); continue; } @@ -1204,6 +1208,15 @@ } continue; } + case Module::Max: { + ConstantInt *DstValue = + mdconst::extract(DstOp->getOperand(2)); + ConstantInt *SrcValue = + mdconst::extract(SrcOp->getOperand(2)); + if (SrcValue->getZExtValue() > DstValue->getZExtValue()) + overrideDstValue(); + break; + } case Module::Append: { MDNode *DstValue = cast(DstOp->getOperand(2)); MDNode *SrcValue = cast(SrcOp->getOperand(2)); Index: llvm/trunk/test/Linker/Inputs/module-flags-pic-2-b.ll =================================================================== --- llvm/trunk/test/Linker/Inputs/module-flags-pic-2-b.ll +++ llvm/trunk/test/Linker/Inputs/module-flags-pic-2-b.ll @@ -1,3 +1,4 @@ -!0 = !{ i32 1, !"PIC Level", i32 2 } +!0 = !{ i32 7, !"PIC Level", i32 2 } +!1 = !{ i32 7, !"PIE Level", i32 2 } -!llvm.module.flags = !{!0} +!llvm.module.flags = !{!0, !1} Index: llvm/trunk/test/Linker/module-flags-pic-2-a.ll =================================================================== --- llvm/trunk/test/Linker/module-flags-pic-2-a.ll +++ llvm/trunk/test/Linker/module-flags-pic-2-a.ll @@ -1,10 +1,11 @@ -; RUN: not llvm-link %s %p/Inputs/module-flags-pic-2-b.ll -S -o - 2> %t -; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s +; RUN: llvm-link %s %p/Inputs/module-flags-pic-2-b.ll -S -o - | FileCheck %s -; test linking modules with two different PIC levels +; test linking modules with two different PIC and PIE levels -!0 = !{ i32 1, !"PIC Level", i32 1 } +!0 = !{ i32 7, !"PIC Level", i32 1 } +!1 = !{ i32 7, !"PIE Level", i32 1 } -!llvm.module.flags = !{!0} +!llvm.module.flags = !{!0, !1} -; CHECK-ERRORS: ERROR: linking module flags 'PIC Level': IDs have conflicting values +; CHECK: !0 = !{i32 7, !"PIC Level", i32 2} +; CHECK: !1 = !{i32 7, !"PIE Level", i32 2} Index: llvm/trunk/test/Verifier/module-flags-1.ll =================================================================== --- llvm/trunk/test/Verifier/module-flags-1.ll +++ llvm/trunk/test/Verifier/module-flags-1.ll @@ -41,6 +41,10 @@ ; CHECK-NOT: invalid value for 'append'-type module flag (expected a metadata node) !18 = !{i32 5, !"flag-4", !{i32 57}} +; Check that any 'max' module flags are valid. +; CHECK: invalid value for 'max' module flag (expected constant integer) +!19 = !{i32 7, !"max", !"max"} + ; Check that any 'require' module flags are valid. ; CHECK: invalid requirement on flag, flag is not present in module !11 = !{i32 3, !"bar", !{!"no-such-flag", i32 52}} @@ -54,4 +58,4 @@ !llvm.module.flags = !{ !0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, - !16, !17, !18 } + !16, !17, !18, !19 }