summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-08-09 04:00:06 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-08-09 04:00:06 +0000
commit606e8ad796f72824f5509e2657c44eca025d4baf (patch)
tree3e7a3992aadb847959ca8ba8d4d58a51a47f9eb8 /utils
parent094da67bd781708e76ab37c76e7a87d86404be05 (diff)
downloadllvm-606e8ad796f72824f5509e2657c44eca025d4baf.tar.gz
llvm-606e8ad796f72824f5509e2657c44eca025d4baf.tar.bz2
llvm-606e8ad796f72824f5509e2657c44eca025d4baf.tar.xz
llvm-mc/AsmParser: Sketch infrastructure for ordering instructions & detecting
ambiguities. - Currently there are 483 ambiguities to resolve. :) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78522 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp120
1 files changed, 106 insertions, 14 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 6948a7ee64..9b12927521 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -78,6 +78,7 @@
#include "Record.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -88,8 +89,8 @@ using namespace llvm;
namespace {
static cl::opt<std::string>
-MatchOneInstr("match-one-instr", cl::desc("Match only the named instruction"),
- cl::init(""));
+MatchPrefix("match-prefix", cl::init(""),
+ cl::desc("Only match instructions with the given prefix"));
}
/// FlattenVariants - Flatten an .td file assembly string by selecting the
@@ -276,11 +277,16 @@ namespace {
/// ClassInfo - Helper class for storing the information about a particular
/// class of operands which can be matched.
struct ClassInfo {
- enum {
+ enum ClassInfoKind {
Token, ///< The class for a particular token.
Register, ///< A register class.
- User ///< A user defined class.
- } Kind;
+ UserClass0 ///< The (first) user defined class, subsequent user defined
+ /// classes are UserClass0+1, and so on.
+ };
+
+ /// Kind - The class kind, which is either a predefined kind, or (UserClass0 +
+ /// N) for the Nth user defined class.
+ unsigned Kind;
/// Name - The class name, suitable for use as an enum.
std::string Name;
@@ -297,6 +303,29 @@ struct ClassInfo {
/// RenderMethod - The name of the operand method to add this operand to an
/// MCInst; this is not valid for Token kinds.
std::string RenderMethod;
+
+ /// operator< - Compare two classes.
+ bool operator<(const ClassInfo &RHS) const {
+ // Incompatible kinds are comparable.
+ if (Kind != RHS.Kind)
+ return Kind < RHS.Kind;
+
+ switch (Kind) {
+ case Token:
+ // Tokens are always comparable.
+ //
+ // FIXME: Compare by enum value.
+ return ValueName < RHS.ValueName;
+
+ case Register:
+ // FIXME: Compare by subset relation.
+ return false;
+
+ default:
+ // FIXME: Allow user defined relation.
+ return false;
+ }
+ }
};
/// InstructionInfo - Helper class for storing the necessary information for an
@@ -331,6 +360,38 @@ struct InstructionInfo {
/// function.
std::string ConversionFnKind;
+ /// 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;
+ }
+
public:
void dump();
};
@@ -460,7 +521,10 @@ AsmMatcherInfo::getOperandClass(const StringRef &Token,
if (ClassName == "Reg") {
Entry->Kind = ClassInfo::Register;
} else {
- Entry->Kind = ClassInfo::User;
+ if (ClassName == "Mem")
+ Entry->Kind = ClassInfo::UserClass0;
+ else
+ Entry->Kind = ClassInfo::UserClass0 + 1;
}
Entry->Name = "MCK_" + ClassName;
Entry->ValueName = OI.Rec->getName();
@@ -479,7 +543,7 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
it != ie; ++it) {
const CodeGenInstruction &CGI = it->second;
- if (!MatchOneInstr.empty() && it->first != MatchOneInstr)
+ if (!StringRef(it->first).startswith(MatchPrefix))
continue;
OwningPtr<InstructionInfo> II(new InstructionInfo);
@@ -537,9 +601,9 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
}
}
-static void ConstructConversionFunctions(CodeGenTarget &Target,
- std::vector<InstructionInfo*> &Infos,
- raw_ostream &OS) {
+static void EmitConvertToMCInst(CodeGenTarget &Target,
+ std::vector<InstructionInfo*> &Infos,
+ raw_ostream &OS) {
// Write the convert function to a separate stream, so we can drop it after
// the enum.
std::string ConvertFnBody;
@@ -902,6 +966,10 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
AsmMatcherInfo Info;
Info.BuildInfo(Target);
+ // Sort the instruction table using the partial order on classes.
+ std::sort(Info.Instructions.begin(), Info.Instructions.end(),
+ less_ptr<InstructionInfo>());
+
DEBUG_WITH_TYPE("instruction_info", {
for (std::vector<InstructionInfo*>::iterator
it = Info.Instructions.begin(), ie = Info.Instructions.end();
@@ -909,11 +977,35 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
(*it)->dump();
});
- // FIXME: At this point we should be able to totally order Infos, if not then
- // we have an ambiguity which the .td file should be forced to resolve.
+ // 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;
- // Generate the terminal actions to convert operands into an MCInst.
- ConstructConversionFunctions(Target, Info.Instructions, OS);
+ InstructionInfo &Next = **it;
+
+ 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 (NumAmbiguous)
+ DEBUG_WITH_TYPE("ambiguous_instrs", {
+ errs() << "warning: " << NumAmbiguous
+ << " ambiguous instructions!\n";
+ });
+
+ // Generate the unified function to convert operands into an MCInst.
+ EmitConvertToMCInst(Target, Info.Instructions, OS);
// Emit the enumeration for classes which participate in matching.
EmitMatchClassEnumeration(Target, Info.Classes, OS);