summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/TableGen/StringMatcher.h7
-rw-r--r--llvm/include/llvm/Target/Target.td8
-rw-r--r--llvm/lib/TableGen/StringMatcher.cpp25
-rw-r--r--llvm/test/TableGen/AllowDuplicateRegisterNames.td86
-rw-r--r--llvm/utils/TableGen/AsmMatcherEmitter.cpp8
5 files changed, 118 insertions, 16 deletions
diff --git a/llvm/include/llvm/TableGen/StringMatcher.h b/llvm/include/llvm/TableGen/StringMatcher.h
index 7c919ffec7b..09d2092d43b 100644
--- a/llvm/include/llvm/TableGen/StringMatcher.h
+++ b/llvm/include/llvm/TableGen/StringMatcher.h
@@ -43,11 +43,12 @@ public:
const std::vector<StringPair> &matches, raw_ostream &os)
: StrVariableName(strVariableName), Matches(matches), OS(os) {}
- void Emit(unsigned Indent = 0) const;
+ void Emit(unsigned Indent = 0, bool IgnoreDuplicates = false) const;
private:
- bool EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches,
- unsigned CharNo, unsigned IndentCount) const;
+ bool EmitStringMatcherForChar(const std::vector<const StringPair *> &Matches,
+ unsigned CharNo, unsigned IndentCount,
+ bool IgnoreDuplicates) const;
};
} // end namespace llvm
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index 4b95e2065bc..82a3be5e63d 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -1174,6 +1174,14 @@ class AsmParser {
// several registers share the same alias (i.e. not a 1:1 mapping).
bit ShouldEmitMatchRegisterAltName = 0;
+ // Set to true if MatchRegisterName and MatchRegisterAltName functions
+ // should be generated even if there are duplicate register names. The
+ // target is responsible for coercing aliased registers as necessary
+ // (e.g. in validateTargetOperandClass), and there are no guarantees about
+ // which numeric register identifier will be returned in the case of
+ // multiple matches.
+ bit AllowDuplicateRegisterNames = 0;
+
// HasMnemonicFirst - Set to false if target instructions don't always
// start with a mnemonic as the first token.
bit HasMnemonicFirst = 1;
diff --git a/llvm/lib/TableGen/StringMatcher.cpp b/llvm/lib/TableGen/StringMatcher.cpp
index 7e510f0c2fd..32599104f6a 100644
--- a/llvm/lib/TableGen/StringMatcher.cpp
+++ b/llvm/lib/TableGen/StringMatcher.cpp
@@ -46,17 +46,18 @@ FindFirstNonCommonLetter(const std::vector<const
/// code to verify that CharNo and later are the same.
///
/// \return - True if control can leave the emitted code fragment.
-bool StringMatcher::
-EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches,
- unsigned CharNo, unsigned IndentCount) const {
+bool StringMatcher::EmitStringMatcherForChar(
+ const std::vector<const StringPair *> &Matches, unsigned CharNo,
+ unsigned IndentCount, bool IgnoreDuplicates) const {
assert(!Matches.empty() && "Must have at least one string to match!");
- std::string Indent(IndentCount*2+4, ' ');
+ std::string Indent(IndentCount * 2 + 4, ' ');
// If we have verified that the entire string matches, we're done: output the
// matching code.
if (CharNo == Matches[0]->first.size()) {
- assert(Matches.size() == 1 && "Had duplicate keys to match on");
-
+ if (Matches.size() > 1 && !IgnoreDuplicates)
+ report_fatal_error("Had duplicate keys to match on");
+
// If the to-execute code has \n's in it, indent each subsequent line.
StringRef Code = Matches[0]->second;
@@ -100,8 +101,9 @@ EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches,
<< NumChars << ") != 0)\n";
OS << Indent << " break;\n";
}
-
- return EmitStringMatcherForChar(Matches, FirstNonCommonLetter, IndentCount);
+
+ return EmitStringMatcherForChar(Matches, FirstNonCommonLetter, IndentCount,
+ IgnoreDuplicates);
}
// Otherwise, we have multiple possible things, emit a switch on the
@@ -116,7 +118,8 @@ EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches,
<< LI->second.size() << " string";
if (LI->second.size() != 1) OS << 's';
OS << " to match.\n";
- if (EmitStringMatcherForChar(LI->second, CharNo+1, IndentCount+1))
+ if (EmitStringMatcherForChar(LI->second, CharNo + 1, IndentCount + 1,
+ IgnoreDuplicates))
OS << Indent << " break;\n";
}
@@ -126,7 +129,7 @@ EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches,
/// Emit - Top level entry point.
///
-void StringMatcher::Emit(unsigned Indent) const {
+void StringMatcher::Emit(unsigned Indent, bool IgnoreDuplicates) const {
// If nothing to match, just fall through.
if (Matches.empty()) return;
@@ -146,7 +149,7 @@ void StringMatcher::Emit(unsigned Indent) const {
OS.indent(Indent*2+2) << "case " << LI->first << ":\t // "
<< LI->second.size()
<< " string" << (LI->second.size() == 1 ? "" : "s") << " to match.\n";
- if (EmitStringMatcherForChar(LI->second, 0, Indent))
+ if (EmitStringMatcherForChar(LI->second, 0, Indent, IgnoreDuplicates))
OS.indent(Indent*2+4) << "break;\n";
}
diff --git a/llvm/test/TableGen/AllowDuplicateRegisterNames.td b/llvm/test/TableGen/AllowDuplicateRegisterNames.td
new file mode 100644
index 00000000000..2ba63c434ca
--- /dev/null
+++ b/llvm/test/TableGen/AllowDuplicateRegisterNames.td
@@ -0,0 +1,86 @@
+// RUN: llvm-tblgen -gen-asm-matcher -I %p/../../include %s | FileCheck %s
+
+// Check that MatchRegisterName and MatchRegisterAltName are generated
+// correctly when multiple registers are defined with the same name and
+// AllowDuplicateRegisterNames is set.
+
+include "llvm/Target/Target.td"
+
+def ArchInstrInfo : InstrInfo;
+
+def ArchAsmParser : AsmParser {
+ let AllowDuplicateRegisterNames = 1;
+ let ShouldEmitMatchRegisterAltName = 1;
+}
+
+def Arch : Target {
+ let InstructionSet = ArchInstrInfo;
+ let AssemblyParsers = [ArchAsmParser];
+}
+
+let Namespace = "Arch" in {
+class ArchReg<string n, list <string> alt, list <RegAltNameIndex> altidx>
+ : Register<n> {
+ let AltNames = alt;
+ let RegAltNameIndices = altidx;
+}
+
+def ABIRegAltName : RegAltNameIndex;
+
+foreach i = 0-3 in {
+ def R#i#_32 : ArchReg<"r"#i, ["x"#i], [ABIRegAltName]>;
+ def R#i#_64 : ArchReg<"r"#i, ["x"#i], [ABIRegAltName]>;
+}
+} // Namespace = "Arch"
+
+def GPR32 : RegisterClass<"Arch", [i32], 32, (add
+ (sequence "R%u_32", 0, 3)
+)>;
+
+def GPR64 : RegisterClass<"Arch", [i64], 64, (add
+ (sequence "R%u_64", 0, 3)
+)>;
+
+// CHECK: static unsigned MatchRegisterName(StringRef Name) {
+// CHECK: switch (Name.size()) {
+// CHECK: default: break;
+// CHECK: case 2: // 8 strings to match.
+// CHECK: if (Name[0] != 'r')
+// CHECK: break;
+// CHECK: switch (Name[1]) {
+// CHECK: default: break;
+// CHECK: case '0': // 2 strings to match.
+// CHECK: return 1; // "r0"
+// CHECK: case '1': // 2 strings to match.
+// CHECK: return 3; // "r1"
+// CHECK: case '2': // 2 strings to match.
+// CHECK: return 5; // "r2"
+// CHECK: case '3': // 2 strings to match.
+// CHECK: return 7; // "r3"
+// CHECK: }
+// CHECK: break;
+// CHECK: }
+// CHECK: return 0;
+// CHECK: }
+
+// CHECK: static unsigned MatchRegisterAltName(StringRef Name) {
+// CHECK: switch (Name.size()) {
+// CHECK: default: break;
+// CHECK: case 2: // 8 strings to match.
+// CHECK: if (Name[0] != 'x')
+// CHECK: break;
+// CHECK: switch (Name[1]) {
+// CHECK: default: break;
+// CHECK: case '0': // 2 strings to match.
+// CHECK: return 1; // "x0"
+// CHECK: case '1': // 2 strings to match.
+// CHECK: return 3; // "x1"
+// CHECK: case '2': // 2 strings to match.
+// CHECK: return 5; // "x2"
+// CHECK: case '3': // 2 strings to match.
+// CHECK: return 7; // "x3"
+// CHECK: }
+// CHECK: break;
+// CHECK: }
+// CHECK: return 0;
+// CHECK: }
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index 72fb53053fd..ee322ad9f33 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -2438,7 +2438,9 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
OS << "static unsigned MatchRegisterName(StringRef Name) {\n";
- StringMatcher("Name", Matches, OS).Emit();
+ bool IgnoreDuplicates =
+ AsmParser->getValueAsBit("AllowDuplicateRegisterNames");
+ StringMatcher("Name", Matches, OS).Emit(0, IgnoreDuplicates);
OS << " return 0;\n";
OS << "}\n\n";
@@ -2469,7 +2471,9 @@ static void emitMatchRegisterAltName(CodeGenTarget &Target, Record *AsmParser,
OS << "static unsigned MatchRegisterAltName(StringRef Name) {\n";
- StringMatcher("Name", Matches, OS).Emit();
+ bool IgnoreDuplicates =
+ AsmParser->getValueAsBit("AllowDuplicateRegisterNames");
+ StringMatcher("Name", Matches, OS).Emit(0, IgnoreDuplicates);
OS << " return 0;\n";
OS << "}\n\n";
OpenPOWER on IntegriCloud