mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
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
This commit is contained in:
parent
a7e7e73c64
commit
f21a88cbf6
@ -6224,7 +6224,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**
|
||||
|
@ -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.
|
||||
|
3
test/Linker/Inputs/module-max-warn.ll
Normal file
3
test/Linker/Inputs/module-max-warn.ll
Normal file
@ -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}
|
12
test/Linker/module-max-warn.ll
Normal file
12
test/Linker/module-max-warn.ll
Normal file
@ -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}
|
Loading…
Reference in New Issue
Block a user