- Added support for parsing HWDiv features using Target Parser.
- Architecture extensions are represented as a bitmap.

Phabricator: http://reviews.llvm.org/D11457
llvm-svn: 243335
diff --git a/llvm/lib/Support/TargetParser.cpp b/llvm/lib/Support/TargetParser.cpp
index 315e0f7..6d43f25 100644
--- a/llvm/lib/Support/TargetParser.cpp
+++ b/llvm/lib/Support/TargetParser.cpp
@@ -113,22 +113,36 @@
 // FIXME: TableGen this.
 struct {
   const char *Name;
-  ARM::ArchExtKind ID;
+  unsigned ID;
 } ARCHExtNames[] = {
-  { "invalid",  ARM::AEK_INVALID },
-  { "crc",      ARM::AEK_CRC },
-  { "crypto",   ARM::AEK_CRYPTO },
-  { "fp",       ARM::AEK_FP },
-  { "idiv",     ARM::AEK_HWDIV },
-  { "mp",       ARM::AEK_MP },
-  { "simd",     ARM::AEK_SIMD },
-  { "sec",      ARM::AEK_SEC },
-  { "virt",     ARM::AEK_VIRT },
-  { "os",       ARM::AEK_OS },
-  { "iwmmxt",   ARM::AEK_IWMMXT },
-  { "iwmmxt2",  ARM::AEK_IWMMXT2 },
-  { "maverick", ARM::AEK_MAVERICK },
-  { "xscale",   ARM::AEK_XSCALE }
+  { "invalid",   ARM::AEK_INVALID },
+  { "none",      ARM::AEK_NONE },
+  { "crc",       ARM::AEK_CRC },
+  { "crypto",    ARM::AEK_CRYPTO },
+  { "fp",        ARM::AEK_FP },
+  { "idiv",     (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV) },
+  { "mp",        ARM::AEK_MP },
+  { "simd",      ARM::AEK_SIMD },
+  { "sec",       ARM::AEK_SEC },
+  { "virt",      ARM::AEK_VIRT },
+  { "os",        ARM::AEK_OS },
+  { "iwmmxt",    ARM::AEK_IWMMXT },
+  { "iwmmxt2",   ARM::AEK_IWMMXT2 },
+  { "maverick",  ARM::AEK_MAVERICK },
+  { "xscale",    ARM::AEK_XSCALE }
+};
+// List of HWDiv names (use getHWDivSynonym) and which architectural
+// features they correspond to (use getHWDivFeatures).
+// FIXME: TableGen this.
+struct {
+  const char *Name;
+  unsigned ID;
+} HWDivNames[] = {
+  { "invalid",    ARM::AEK_INVALID },
+  { "none",       ARM::AEK_NONE },
+  { "thumb",      ARM::AEK_HWDIV },
+  { "arm",        ARM::AEK_HWDIVARM },
+  { "arm,thumb", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV) }
 };
 // List of CPU names and their arches.
 // The same CPU can have multiple arches and can be default on multiple arches.
@@ -266,6 +280,25 @@
   return ARM::FK_INVALID;
 }
 
+bool ARMTargetParser::getHWDivFeatures(unsigned HWDivKind,
+                                       std::vector<const char *> &Features) {
+
+  if (HWDivKind == ARM::AEK_INVALID)
+    return false;
+
+   if (HWDivKind & ARM::AEK_HWDIVARM)
+    Features.push_back("+hwdiv-arm");
+  else
+    Features.push_back("-hwdiv-arm");
+
+  if (HWDivKind & ARM::AEK_HWDIV)
+    Features.push_back("+hwdiv");
+  else
+    Features.push_back("-hwdiv");
+
+  return true;
+}
+
 bool ARMTargetParser::getFPUFeatures(unsigned FPUKind,
                                      std::vector<const char *> &Features) {
 
@@ -372,9 +405,19 @@
 }
 
 const char *ARMTargetParser::getArchExtName(unsigned ArchExtKind) {
-  if (ArchExtKind >= ARM::AEK_LAST)
-    return nullptr;
-  return ARCHExtNames[ArchExtKind].Name;
+  for (const auto AE : ARCHExtNames) {
+    if (ArchExtKind == AE.ID)
+      return AE.Name;
+  }
+  return nullptr;
+}
+
+const char *ARMTargetParser::getHWDivName(unsigned HWDivKind) {
+  for (const auto D : HWDivNames) {
+    if (HWDivKind == D.ID)
+      return D.Name;
+  }
+  return nullptr;
 }
 
 const char *ARMTargetParser::getDefaultCPU(StringRef Arch) {
@@ -394,6 +437,12 @@
 // Parsers
 // ======================================================= //
 
+StringRef ARMTargetParser::getHWDivSynonym(StringRef HWDiv) {
+  return StringSwitch<StringRef>(HWDiv)
+    .Case("thumb,arm", "arm,thumb")
+    .Default(HWDiv);
+}
+
 StringRef ARMTargetParser::getFPUSynonym(StringRef FPU) {
   return StringSwitch<StringRef>(FPU)
     .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
@@ -477,6 +526,15 @@
   return A;
 }
 
+unsigned ARMTargetParser::parseHWDiv(StringRef HWDiv) {
+  StringRef Syn = getHWDivSynonym(HWDiv);
+  for (const auto D : HWDivNames) {
+    if (Syn == D.Name)
+      return D.ID;
+  }
+  return ARM::AEK_INVALID;
+}
+
 unsigned ARMTargetParser::parseFPU(StringRef FPU) {
   StringRef Syn = getFPUSynonym(FPU);
   for (const auto F : FPUNames) {