diff options
author | David Blaikie <dblaikie@gmail.com> | 2020-02-06 14:37:23 -0800 |
---|---|---|
committer | Hans Wennborg <hans@chromium.org> | 2020-02-11 10:36:46 +0100 |
commit | 4e6ec0fff658cbe29e70f46491917202baa061c0 (patch) | |
tree | 596d33ed5e36fb0cc44ca8315a81835ae165a243 | |
parent | 699e2a6c5551eacf10be7e64f579120954f55b10 (diff) | |
download | bcm5719-llvm-4e6ec0fff658cbe29e70f46491917202baa061c0.tar.gz bcm5719-llvm-4e6ec0fff658cbe29e70f46491917202baa061c0.zip |
IR Linking: Support merging Warning+Max module metadata flags
Summary:
Debug Info Version was changed to use "Max" instead of "Warning" per the
original design intent - but this maxes old/new IR unlinkable, since
mismatched merge styles are a linking failure.
It seems possible/maybe reasonable to actually support the combination
of these two flags: Warn, but then use the maximum value rather than the
first value/earlier module's value.
Reviewers: tejohnson
Differential Revision: https://reviews.llvm.org/D74257
(cherry picked from commit ba9cae58bbdd41451ee67773c9d0f90a01756f12)
-rw-r--r-- | llvm/docs/LangRef.rst | 4 | ||||
-rw-r--r-- | llvm/lib/Linker/IRMover.cpp | 70 | ||||
-rw-r--r-- | llvm/test/Linker/Inputs/module-max-warn.ll | 3 | ||||
-rw-r--r-- | llvm/test/Linker/module-max-warn.ll | 12 |
4 files changed, 65 insertions, 24 deletions
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index a64974c2d90..0ae374de4b6 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -6114,7 +6114,9 @@ The following behaviors are supported: * - 2 - **Warning** Emits a warning if two values disagree. The result value will be the - operand for the flag from the first module being linked. + operand for the flag from the first module being linked, or the max + if the other module uses **Max** (in which case the resulting flag + will be **Max**). * - 3 - **Require** diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp index e13656ed1c1..af934cc8b9b 100644 --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -1277,11 +1277,17 @@ Error IRLinker::linkModuleFlagsMetadata() { } // Diagnose inconsistent merge behavior types. - if (SrcBehaviorValue != DstBehaviorValue) - return stringErr("linking module flags '" + ID->getString() + - "': IDs have conflicting behaviors in '" + - SrcM->getModuleIdentifier() + "' and '" + - DstM.getModuleIdentifier() + "'"); + if (SrcBehaviorValue != DstBehaviorValue) { + bool MaxAndWarn = (SrcBehaviorValue == Module::Max && + DstBehaviorValue == Module::Warning) || + (DstBehaviorValue == Module::Max && + SrcBehaviorValue == Module::Warning); + if (!MaxAndWarn) + return stringErr("linking module flags '" + ID->getString() + + "': IDs have conflicting behaviors in '" + + SrcM->getModuleIdentifier() + "' and '" + + DstM.getModuleIdentifier() + "'"); + } auto replaceDstValue = [&](MDNode *New) { Metadata *FlagOps[] = {DstOp->getOperand(0), ID, New}; @@ -1290,6 +1296,40 @@ Error IRLinker::linkModuleFlagsMetadata() { Flags[ID].first = Flag; }; + // Emit a warning if the values differ and either source or destination + // request Warning behavior. + if ((DstBehaviorValue == Module::Warning || + SrcBehaviorValue == Module::Warning) && + SrcOp->getOperand(2) != DstOp->getOperand(2)) { + std::string Str; + raw_string_ostream(Str) + << "linking module flags '" << ID->getString() + << "': IDs have conflicting values ('" << *SrcOp->getOperand(2) + << "' from " << SrcM->getModuleIdentifier() << " with '" + << *DstOp->getOperand(2) << "' from " << DstM.getModuleIdentifier() + << ')'; + emitWarning(Str); + } + + // Choose the maximum if either source or destination request Max behavior. + if (DstBehaviorValue == Module::Max || SrcBehaviorValue == Module::Max) { + ConstantInt *DstValue = + mdconst::extract<ConstantInt>(DstOp->getOperand(2)); + ConstantInt *SrcValue = + mdconst::extract<ConstantInt>(SrcOp->getOperand(2)); + + // The resulting flag should have a Max behavior, and contain the maximum + // value from between the source and destination values. + Metadata *FlagOps[] = { + (DstBehaviorValue != Module::Max ? SrcOp : DstOp)->getOperand(0), ID, + (SrcValue->getZExtValue() > DstValue->getZExtValue() ? SrcOp : DstOp) + ->getOperand(2)}; + MDNode *Flag = MDNode::get(DstM.getContext(), FlagOps); + DstModFlags->setOperand(DstIndex, Flag); + Flags[ID].first = Flag; + continue; + } + // Perform the merge for standard behavior types. switch (SrcBehaviorValue) { case Module::Require: @@ -1305,26 +1345,9 @@ Error IRLinker::linkModuleFlagsMetadata() { continue; } case Module::Warning: { - // Emit a warning if the values differ. - if (SrcOp->getOperand(2) != DstOp->getOperand(2)) { - std::string str; - raw_string_ostream(str) - << "linking module flags '" << ID->getString() - << "': IDs have conflicting values ('" << *SrcOp->getOperand(2) - << "' from " << SrcM->getModuleIdentifier() << " with '" - << *DstOp->getOperand(2) << "' from " << DstM.getModuleIdentifier() - << ')'; - emitWarning(str); - } - continue; + break; } case Module::Max: { - ConstantInt *DstValue = - mdconst::extract<ConstantInt>(DstOp->getOperand(2)); - ConstantInt *SrcValue = - mdconst::extract<ConstantInt>(SrcOp->getOperand(2)); - if (SrcValue->getZExtValue() > DstValue->getZExtValue()) - overrideDstValue(); break; } case Module::Append: { @@ -1350,6 +1373,7 @@ Error IRLinker::linkModuleFlagsMetadata() { break; } } + } // Check all of the requirements. diff --git a/llvm/test/Linker/Inputs/module-max-warn.ll b/llvm/test/Linker/Inputs/module-max-warn.ll new file mode 100644 index 00000000000..2d6a1004d19 --- /dev/null +++ b/llvm/test/Linker/Inputs/module-max-warn.ll @@ -0,0 +1,3 @@ +!llvm.module.flags = !{!0, !1} +!0 = !{i32 2, !"Combine Max and Warn", i32 4} +!1 = !{i32 7, !"Combine Warn and Max", i32 5} diff --git a/llvm/test/Linker/module-max-warn.ll b/llvm/test/Linker/module-max-warn.ll new file mode 100644 index 00000000000..b05688446ed --- /dev/null +++ b/llvm/test/Linker/module-max-warn.ll @@ -0,0 +1,12 @@ +; RUN: llvm-link %s %p/Inputs/module-max-warn.ll -S -o - 2>&1 | FileCheck %s + +; CHECK: warning: linking module flags 'Combine Max and Warn': IDs have conflicting values ('i32 4' from {{.*}}/test/Linker/Inputs/module-max-warn.ll with 'i32 2' from llvm-link) +; CHECK: warning: linking module flags 'Combine Warn and Max': IDs have conflicting values ('i32 5' from {{.*}}/test/Linker/Inputs/module-max-warn.ll with 'i32 3' from llvm-link) + + +; CHECK: !0 = !{i32 7, !"Combine Max and Warn", i32 4} +; CHECK: !1 = !{i32 7, !"Combine Warn and Max", i32 5} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 7, !"Combine Max and Warn", i32 2} +!1 = !{i32 2, !"Combine Warn and Max", i32 3} |