[TableGen] Add 'register alternative name matching' support
authorDylan McKay <dylanmckay34@gmail.com>
Wed, 3 Feb 2016 10:30:16 +0000 (10:30 +0000)
committerDylan McKay <dylanmckay34@gmail.com>
Wed, 3 Feb 2016 10:30:16 +0000 (10:30 +0000)
Summary:
This adds a new attribute which targets can set in TableGen which causes a function to be generated which matches register alternative names. This is very similar to `ShouldEmitMatchRegisterName`, except it works on alt names.

This patch is currently used by the out of tree part of the AVR backend. It reduces code duplication greatly, and has the effect that you do not need to hardcode altname to register mappings in C++.

It will not work on targets which have registers which share the same aliases.

Reviewers: stoklund, arsenm, dsanders, hfinkel, vkalintiris

Subscribers: hfinkel, dylanmckay, llvm-commits

Differential Revision: http://reviews.llvm.org/D16312

llvm-svn: 259636

llvm/include/llvm/Target/Target.td
llvm/utils/TableGen/AsmMatcherEmitter.cpp

index c5e8cfe..275be59 100644 (file)
@@ -941,6 +941,14 @@ class AsmParser {
   // written register name matcher
   bit ShouldEmitMatchRegisterName = 1;
 
+  // Set to true if the target needs a generated 'alternative register name'
+  // matcher.
+  //
+  // This generates a function which can be used to lookup registers from
+  // their aliases. This function will fail when called on targets where
+  // several registers share the same alias (i.e. not a 1:1 mapping).
+  bit ShouldEmitMatchRegisterAltName = 0;
+
   // HasMnemonicFirst - Set to false if target instructions don't always
   // start with a mnemonic as the first token.
   bit HasMnemonicFirst = 1;
index 907eab6..07dbd28 100644 (file)
@@ -2276,6 +2276,37 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
   OS << "}\n\n";
 }
 
+/// Emit the function to match a string to the target
+/// specific register enum.
+static void emitMatchRegisterAltName(CodeGenTarget &Target, Record *AsmParser,
+                                     raw_ostream &OS) {
+  // Construct the match list.
+  std::vector<StringMatcher::StringPair> Matches;
+  const auto &Regs = Target.getRegBank().getRegisters();
+  for (const CodeGenRegister &Reg : Regs) {
+
+    auto AltNames = Reg.TheDef->getValueAsListOfStrings("AltNames");
+
+    for (auto AltName : AltNames) {
+      AltName = StringRef(AltName).trim();
+
+      // don't handle empty alternative names
+      if (AltName.empty())
+        continue;
+
+      Matches.emplace_back(AltName,
+                           "return " + utostr(Reg.EnumValue) + ";");
+    }
+  }
+
+  OS << "static unsigned MatchRegisterAltName(StringRef Name) {\n";
+
+  StringMatcher("Name", Matches, OS).Emit();
+
+  OS << "  return 0;\n";
+  OS << "}\n\n";
+}
+
 static const char *getMinimalTypeForRange(uint64_t Range) {
   assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large");
   if (Range > 0xFFFFFFFFULL)
@@ -2816,6 +2847,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
   if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterName"))
     emitMatchRegisterName(Target, AsmParser, OS);
 
+  if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterAltName"))
+    emitMatchRegisterAltName(Target, AsmParser, OS);
+
   OS << "#endif // GET_REGISTER_MATCHER\n\n";
 
   OS << "\n#ifdef GET_SUBTARGET_FEATURE_NAME\n";