mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
llvm-mc/AsmParser: Separate instruction ordering for ambiguity detection.
- We want the ordering operation to be simple, since we run it on every match. The old ordering is also not a strict weak ordering when there are ambiguities, which makes MSVC unhappy. - While we are at it, detect all ambiguities instead of just the adjacent ones. There are actually 655, for X86. llvm-svn: 78526
This commit is contained in:
parent
326491672e
commit
1d76f6d593
@ -263,7 +263,7 @@ static bool IsAssemblerInstruction(const StringRef &Name,
|
||||
DEBUG({
|
||||
errs() << "warning: '" << Name << "': "
|
||||
<< "ignoring instruction; tied operand '"
|
||||
<< Tokens[i] << "', \n";
|
||||
<< Tokens[i] << "'\n";
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@ -368,36 +368,47 @@ struct InstructionInfo {
|
||||
|
||||
/// operator< - Compare two instructions.
|
||||
bool operator<(const InstructionInfo &RHS) const {
|
||||
// Order first by the number of operands (which is unambiguous).
|
||||
if (Operands.size() != RHS.Operands.size())
|
||||
return Operands.size() < RHS.Operands.size();
|
||||
|
||||
// Otherwise, order by lexicographic comparison of tokens and operand kinds
|
||||
// (these can never be ambiguous).
|
||||
for (unsigned i = 0, e = Operands.size(); i != e; ++i)
|
||||
if (Operands[i].Class->Kind != RHS.Operands[i].Class->Kind ||
|
||||
Operands[i].Class->Kind == ClassInfo::Token)
|
||||
if (*Operands[i].Class < *RHS.Operands[i].Class)
|
||||
return true;
|
||||
|
||||
// Finally, order by the component wise comparison of operand classes. We
|
||||
// don't want to rely on the lexigraphic ordering of elements, so we define
|
||||
// only define the ordering when it is unambiguous. That is, when some pair
|
||||
// compares less than and no pair compares greater than.
|
||||
|
||||
// Check that no pair compares greater than.
|
||||
for (unsigned i = 0, e = Operands.size(); i != e; ++i)
|
||||
if (*RHS.Operands[i].Class < *Operands[i].Class)
|
||||
return false;
|
||||
|
||||
// Otherwise, return true if some pair compares less than.
|
||||
for (unsigned i = 0, e = Operands.size(); i != e; ++i)
|
||||
if (*Operands[i].Class < *RHS.Operands[i].Class)
|
||||
return true;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// CouldMatchAmiguouslyWith - Check whether this instruction could
|
||||
/// ambiguously match the same set of operands as \arg RHS (without being a
|
||||
/// strictly superior match).
|
||||
bool CouldMatchAmiguouslyWith(const InstructionInfo &RHS) {
|
||||
// The number of operands is unambiguous.
|
||||
if (Operands.size() != RHS.Operands.size())
|
||||
return false;
|
||||
|
||||
// Tokens and operand kinds are unambiguous (assuming a correct target
|
||||
// specific parser).
|
||||
for (unsigned i = 0, e = Operands.size(); i != e; ++i)
|
||||
if (Operands[i].Class->Kind != RHS.Operands[i].Class->Kind ||
|
||||
Operands[i].Class->Kind == ClassInfo::Token)
|
||||
if (*Operands[i].Class < *RHS.Operands[i].Class ||
|
||||
*RHS.Operands[i].Class < *Operands[i].Class)
|
||||
return false;
|
||||
|
||||
// Otherwise, this operand could commute if all operands are equivalent, or
|
||||
// there is a pair of operands that compare less than and a pair that
|
||||
// compare greater than.
|
||||
bool HasLT = false, HasGT = false;
|
||||
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
|
||||
if (*Operands[i].Class < *RHS.Operands[i].Class)
|
||||
HasLT = true;
|
||||
if (*RHS.Operands[i].Class < *Operands[i].Class)
|
||||
HasGT = true;
|
||||
}
|
||||
|
||||
return !(HasLT ^ HasGT);
|
||||
}
|
||||
|
||||
public:
|
||||
void dump();
|
||||
};
|
||||
@ -991,23 +1002,21 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||
|
||||
// Check for ambiguous instructions.
|
||||
unsigned NumAmbiguous = 0;
|
||||
for (std::vector<InstructionInfo*>::const_iterator it =
|
||||
Info.Instructions.begin(), ie = Info.Instructions.end() - 1;
|
||||
it != ie;) {
|
||||
InstructionInfo &II = **it;
|
||||
++it;
|
||||
|
||||
InstructionInfo &Next = **it;
|
||||
for (unsigned i = 0, e = Info.Instructions.size(); i != e; ++i) {
|
||||
for (unsigned j = i + 1; j != e; ++j) {
|
||||
InstructionInfo &A = *Info.Instructions[i];
|
||||
InstructionInfo &B = *Info.Instructions[j];
|
||||
|
||||
if (!(II < Next)){
|
||||
DEBUG_WITH_TYPE("ambiguous_instrs", {
|
||||
errs() << "warning: ambiguous instruction match:\n";
|
||||
II.dump();
|
||||
errs() << "\nis incomparable with:\n";
|
||||
Next.dump();
|
||||
errs() << "\n\n";
|
||||
});
|
||||
++NumAmbiguous;
|
||||
if (A.CouldMatchAmiguouslyWith(B)) {
|
||||
DEBUG_WITH_TYPE("ambiguous_instrs", {
|
||||
errs() << "warning: ambiguous instruction match:\n";
|
||||
A.dump();
|
||||
errs() << "\nis incomparable with:\n";
|
||||
B.dump();
|
||||
errs() << "\n\n";
|
||||
});
|
||||
++NumAmbiguous;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NumAmbiguous)
|
||||
|
Loading…
Reference in New Issue
Block a user