https://github.com/aengelke created 
https://github.com/llvm/llvm-project/pull/206937

Make the tables that contain strings relocation-free and move them to
the .cpp file. This reduces the size of .data.rel.ro of libLLVM.so by
~9kiB.


>From a99b803017af3bca32f1dc6ed1f42dccaa0f7f26 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Wed, 1 Jul 2026 10:12:48 +0000
Subject: [PATCH] [spr] initial version

Created using spr 1.3.8-wip
---
 clang/lib/Driver/ToolChain.cpp                |  17 +-
 clang/lib/Driver/ToolChains/Arch/ARM.cpp      |   7 +-
 clang/lib/Driver/ToolChains/CommonArgs.cpp    |   3 +-
 .../llvm/TargetParser/ARMTargetParser.h       |  91 +------
 llvm/lib/TargetParser/ARMTargetParser.cpp     | 229 ++++++++++++------
 .../TargetParser/TargetParserTest.cpp         |  23 +-
 6 files changed, 185 insertions(+), 185 deletions(-)

diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 21d2fbef59fc6..317263d581732 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -25,6 +25,7 @@
 #include "clang/Driver/SanitizerArgs.h"
 #include "clang/Driver/XRayArgs.h"
 #include "clang/Options/Options.h"
+#include "llvm/ADT/Enum.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
@@ -351,14 +352,14 @@ static void getARMMultilibFlags(const Driver &D, const 
llvm::Triple &Triple,
   llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
                                        UnifiedFeatures.end());
   std::vector<std::string> MArch;
-  for (const auto &Ext : ARM::ARCHExtNames)
-    if (!Ext.Name.empty())
-      if (FeatureSet.contains(Ext.Feature))
-        MArch.push_back(Ext.Name.str());
-  for (const auto &Ext : ARM::ARCHExtNames)
-    if (!Ext.Name.empty())
-      if (FeatureSet.contains(Ext.NegFeature))
-        MArch.push_back(("no" + Ext.Name).str());
+  for (const auto &Ext : ARM::getArchExts())
+    if (!Ext.name().empty())
+      if (FeatureSet.contains(Ext.name(1)))
+        MArch.push_back(Ext.name().str());
+  for (const auto &Ext : ARM::getArchExts())
+    if (!Ext.name().empty())
+      if (FeatureSet.contains(Ext.name(2)))
+        MArch.push_back(("no" + Ext.name()).str());
   MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());
   Result.push_back(llvm::join(MArch, "+"));
 
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp 
b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 7d9c1f0bd3d40..a8f7f81726080 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -792,10 +792,9 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver 
&D,
   const auto ItSimd =
       llvm::find_if(llvm::reverse(Features),
                     [](const StringRef F) { return F.contains("neon"); });
-  const bool FPUSupportsNeon = (llvm::ARM::FPUNames[FPUKind].NeonSupport ==
-                                llvm::ARM::NeonSupportLevel::Neon) ||
-                               (llvm::ARM::FPUNames[FPUKind].NeonSupport ==
-                                llvm::ARM::NeonSupportLevel::Crypto);
+  auto NeonSupport = llvm::ARM::getFPUNeonSupportLevel(FPUKind);
+  bool FPUSupportsNeon = NeonSupport == llvm::ARM::NeonSupportLevel::Neon ||
+                         NeonSupport == llvm::ARM::NeonSupportLevel::Crypto;
   if (ItSimd != Features.rend())
     HasSimd = ItSimd->starts_with("+");
   if (!HasSimd && FPUSupportsNeon)
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index dfd13fbe8a4eb..ac90b8335c3ea 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -927,7 +927,8 @@ void tools::getTargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
 
   for (auto Feature : unifyTargetFeatures(Features)) {
     CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature");
-    CmdArgs.push_back(Feature.data());
+    // Feature strings may not be null-terminated.
+    CmdArgs.push_back(Args.MakeArgString(Feature));
   }
 }
 
diff --git a/llvm/include/llvm/TargetParser/ARMTargetParser.h 
b/llvm/include/llvm/TargetParser/ARMTargetParser.h
index 919598c894cd5..50bf76f14ac0e 100644
--- a/llvm/include/llvm/TargetParser/ARMTargetParser.h
+++ b/llvm/include/llvm/TargetParser/ARMTargetParser.h
@@ -23,6 +23,7 @@
 
 namespace llvm {
 
+template <typename, unsigned> class EnumStrings;
 class Triple;
 
 namespace ARM {
@@ -78,30 +79,6 @@ enum ArchExtKind : uint64_t {
   AEK_XSCALE = 1ULL << 63,
 };
 
-// List of Arch Extension names.
-struct ExtName {
-  StringRef Name;
-  uint64_t ID;
-  StringRef Feature;
-  StringRef NegFeature;
-};
-
-constexpr ExtName ARCHExtNames[] = {
-#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE)                       
\
-  {NAME, ID, FEATURE, NEGFEATURE},
-#include "ARMTargetParser.def"
-};
-
-// List of HWDiv names (use getHWDivSynonym) and which architectural
-// features they correspond to (use getHWDivFeatures).
-constexpr struct {
-  StringRef Name;
-  uint64_t ID;
-} HWDivNames[] = {
-#define ARM_HW_DIV_NAME(NAME, ID) {NAME, ID},
-#include "ARMTargetParser.def"
-};
-
 // Arch names.
 enum class ArchKind {
 #define ARM_ARCH(NAME, ID, CPU_ATTR, ARCH_FEATURE, ARCH_ATTR, ARCH_FPU,        
\
@@ -110,23 +87,6 @@ enum class ArchKind {
 #include "ARMTargetParser.def"
 };
 
-// List of CPU names and their arches.
-// The same CPU can have multiple arches and can be default on multiple arches.
-// When finding the Arch for a CPU, first-found prevails. Sort them 
accordingly.
-// When this becomes table-generated, we'd probably need two tables.
-struct CpuNames {
-  StringRef Name;
-  ArchKind ArchID;
-  bool Default; // is $Name the default CPU for $ArchID ?
-  uint64_t DefaultExtensions;
-};
-
-constexpr CpuNames CPUNames[] = {
-#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)           
\
-  {NAME, ARM::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT},
-#include "ARMTargetParser.def"
-};
-
 // FPU names.
 enum FPUKind {
 #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) KIND,
@@ -170,52 +130,6 @@ enum class NeonSupportLevel {
 // v6/v7/v8 Profile
 enum class ProfileKind { INVALID = 0, A, R, M };
 
-// List of canonical FPU names (use getFPUSynonym) and which architectural
-// features they correspond to (use getFPUFeatures).
-// The entries must appear in the order listed in ARM::FPUKind for correct
-// indexing
-struct FPUName {
-  StringRef Name;
-  FPUKind ID;
-  FPUVersion FPUVer;
-  NeonSupportLevel NeonSupport;
-  FPURestriction Restriction;
-};
-
-static constexpr FPUName FPUNames[] = {
-#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION)                
\
-  {NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION},
-#include "llvm/TargetParser/ARMTargetParser.def"
-};
-
-// List of canonical arch names (use getArchSynonym).
-// This table also provides the build attribute fields for CPU arch
-// and Arch ID, according to the Addenda to the ARM ABI, chapters
-// 2.4 and 2.3.5.2 respectively.
-// FIXME: SubArch values were simplified to fit into the expectations
-// of the triples and are not conforming with their official names.
-// Check to see if the expectation should be changed.
-struct ArchNames {
-  StringRef Name;
-  StringRef CPUAttr; // CPU class in build attributes.
-  StringRef ArchFeature;
-  FPUKind DefaultFPU;
-  uint64_t ArchBaseExtensions;
-  ArchKind ID;
-  ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
-
-  // Return ArchFeature without the leading "+".
-  StringRef getSubArch() const { return ArchFeature.substr(1); }
-};
-
-static constexpr ArchNames ARMArchNames[] = {
-#define ARM_ARCH(NAME, ID, CPU_ATTR, ARCH_FEATURE, ARCH_ATTR, ARCH_FPU,        
\
-                 ARCH_BASE_EXT)                                                
\
-  {NAME,          CPU_ATTR,     ARCH_FEATURE, ARCH_FPU,                        
\
-   ARCH_BASE_EXT, ArchKind::ID, ARCH_ATTR},
-#include "llvm/TargetParser/ARMTargetParser.def"
-};
-
 inline ArchKind &operator--(ArchKind &Kind) {
   assert((Kind >= ArchKind::ARMV8A && Kind <= ArchKind::ARMV9_3A) &&
          "We only expect operator-- to be called with ARMV8/V9");
@@ -246,6 +160,9 @@ LLVM_ABI StringRef getArchName(ArchKind AK);
 LLVM_ABI unsigned getArchAttr(ArchKind AK);
 LLVM_ABI StringRef getCPUAttr(ArchKind AK);
 LLVM_ABI StringRef getSubArch(ArchKind AK);
+/// Get list of architecture extensions. The name strings are: 0=Name,
+/// 1=PosFeature (incl. "+"), 2=NegFeature (incl. "-").
+LLVM_ABI EnumStrings<uint64_t, 3> getArchExts();
 LLVM_ABI StringRef getArchExtName(uint64_t ArchExtKind);
 LLVM_ABI StringRef getArchExtFeature(StringRef ArchExt);
 LLVM_ABI bool appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK,
diff --git a/llvm/lib/TargetParser/ARMTargetParser.cpp 
b/llvm/lib/TargetParser/ARMTargetParser.cpp
index 709e5f05e3bb9..391aa31a6cb25 100644
--- a/llvm/lib/TargetParser/ARMTargetParser.cpp
+++ b/llvm/lib/TargetParser/ARMTargetParser.cpp
@@ -12,6 +12,7 @@
 
//===----------------------------------------------------------------------===//
 
 #include "llvm/TargetParser/ARMTargetParser.h"
+#include "llvm/ADT/Enum.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
@@ -21,6 +22,79 @@
 
 using namespace llvm;
 
+namespace {
+using namespace llvm::ARM;
+
+// List of Arch Extension names.
+constexpr EnumStringDef<uint64_t, 3> ExtNameDefs[] = {
+#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE)                       
\
+  {{NAME, FEATURE, NEGFEATURE}, ID},
+#include "llvm/TargetParser/ARMTargetParser.def"
+};
+static constexpr auto ExtNames = BUILD_ENUM_STRINGS(ExtNameDefs);
+
+// List of CPU names and their arches.
+// The same CPU can have multiple arches and can be default on multiple arches.
+// When finding the Arch for a CPU, first-found prevails. Sort them 
accordingly.
+// When this becomes table-generated, we'd probably need two tables.
+struct CpuName {
+  ArchKind ArchID;
+  FPUKind DefaultFPU;
+  bool Default; // is $Name the default CPU for $ArchID ?
+  uint64_t DefaultExtensions;
+};
+
+constexpr EnumStringDef<CpuName> CPUNameDefs[] = {
+#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)           
\
+  {{NAME}, {ARM::ArchKind::ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT}},
+#include "llvm/TargetParser/ARMTargetParser.def"
+};
+static constexpr auto CPUNames = BUILD_ENUM_STRINGS(CPUNameDefs);
+
+// List of canonical FPU names (use getFPUSynonym) and which architectural
+// features they correspond to (use getFPUFeatures).
+// The entries must appear in the order listed in ARM::FPUKind for correct
+// indexing.
+struct FPUName {
+  FPUKind ID;
+  FPUVersion FPUVer;
+  NeonSupportLevel NeonSupport;
+  FPURestriction Restriction;
+};
+
+constexpr EnumStringDef<FPUName> FPUNameDefs[] = {
+#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION)                
\
+  {{NAME}, {KIND, VERSION, NEON_SUPPORT, RESTRICTION}},
+#include "llvm/TargetParser/ARMTargetParser.def"
+};
+static constexpr auto FPUNames = BUILD_ENUM_STRINGS(FPUNameDefs);
+
+// List of canonical arch names (use getArchSynonym).
+// This table also provides the build attribute fields for CPU arch
+// and Arch ID, according to the Addenda to the ARM ABI, chapters
+// 2.4 and 2.3.5.2 respectively.
+// FIXME: SubArch values were simplified to fit into the expectations
+// of the triples and are not conforming with their official names.
+// Check to see if the expectation should be changed.
+struct ArchName {
+  FPUKind DefaultFPU;
+  uint64_t ArchBaseExtensions;
+  ArchKind ID;
+  ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
+};
+
+// Enum string indices: 0 = Name, 1 = CPUAttr, 2 = ArchFeature (incl. "+").
+constexpr EnumStringDef<ArchName, 3> ArchNameDefs[] = {
+#define ARM_ARCH(NAME, ID, CPU_ATTR, ARCH_FEATURE, ARCH_ATTR, ARCH_FPU,        
\
+                 ARCH_BASE_EXT)                                                
\
+  {{NAME, CPU_ATTR, ARCH_FEATURE},                                             
\
+   {ARCH_FPU, ARCH_BASE_EXT, ArchKind::ID, ARCH_ATTR}},
+#include "llvm/TargetParser/ARMTargetParser.def"
+};
+static constexpr auto ArchNames = BUILD_ENUM_STRINGS(ArchNameDefs);
+
+} // end anonymous namespace
+
 static StringRef getHWDivSynonym(StringRef HWDiv) {
   return StringSwitch<StringRef>(HWDiv)
       .Case("thumb,arm", "arm,thumb")
@@ -31,9 +105,9 @@ static StringRef getHWDivSynonym(StringRef HWDiv) {
 ARM::ArchKind ARM::parseArch(StringRef Arch) {
   Arch = getCanonicalArchName(Arch);
   StringRef Syn = getArchSynonym(Arch);
-  for (const auto &A : ARMArchNames) {
-    if (A.Name.ends_with(Syn))
-      return A.ID;
+  for (const auto &A : ArchNames) {
+    if (A.name(0).ends_with(Syn))
+      return A.value().ID;
   }
   return ArchKind::INVALID;
 }
@@ -194,8 +268,8 @@ bool ARM::getFPUFeatures(ARM::FPUKind FPUKind,
   };
 
   for (const auto &Info: FPUFeatureInfoList) {
-    if (FPUNames[FPUKind].FPUVer >= Info.MinVersion &&
-        FPUNames[FPUKind].Restriction <= Info.MaxRestriction)
+    if (FPUNames[FPUKind].value().FPUVer >= Info.MinVersion &&
+        FPUNames[FPUKind].value().Restriction <= Info.MaxRestriction)
       Features.push_back(Info.PlusName);
     else
       Features.push_back(Info.MinusName);
@@ -211,7 +285,7 @@ bool ARM::getFPUFeatures(ARM::FPUKind FPUKind,
   };
 
   for (const auto &Info: NeonFeatureInfoList) {
-    if (FPUNames[FPUKind].NeonSupport >= Info.MinSupportLevel)
+    if (FPUNames[FPUKind].value().NeonSupport >= Info.MinSupportLevel)
       Features.push_back(Info.PlusName);
     else
       Features.push_back(Info.MinusName);
@@ -223,8 +297,8 @@ bool ARM::getFPUFeatures(ARM::FPUKind FPUKind,
 ARM::FPUKind ARM::parseFPU(StringRef FPU) {
   StringRef Syn = getFPUSynonym(FPU);
   for (const auto &F : FPUNames) {
-    if (Syn == F.Name)
-      return F.ID;
+    if (Syn == F.name())
+      return F.value().ID;
   }
   return FK_INVALID;
 }
@@ -232,7 +306,7 @@ ARM::FPUKind ARM::parseFPU(StringRef FPU) {
 ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(ARM::FPUKind FPUKind) {
   if (FPUKind >= FK_LAST)
     return NeonSupportLevel::None;
-  return FPUNames[FPUKind].NeonSupport;
+  return FPUNames[FPUKind].value().NeonSupport;
 }
 
 StringRef ARM::getFPUSynonym(StringRef FPU) {
@@ -255,43 +329,42 @@ StringRef ARM::getFPUSynonym(StringRef FPU) {
 StringRef ARM::getFPUName(ARM::FPUKind FPUKind) {
   if (FPUKind >= FK_LAST)
     return StringRef();
-  return FPUNames[FPUKind].Name;
+  return FPUNames[FPUKind].name();
 }
 
 ARM::FPUVersion ARM::getFPUVersion(ARM::FPUKind FPUKind) {
   if (FPUKind >= FK_LAST)
     return FPUVersion::NONE;
-  return FPUNames[FPUKind].FPUVer;
+  return FPUNames[FPUKind].value().FPUVer;
 }
 
 ARM::FPURestriction ARM::getFPURestriction(ARM::FPUKind FPUKind) {
   if (FPUKind >= FK_LAST)
     return FPURestriction::None;
-  return FPUNames[FPUKind].Restriction;
+  return FPUNames[FPUKind].value().Restriction;
 }
 
 ARM::FPUKind ARM::getDefaultFPU(StringRef CPU, ARM::ArchKind AK) {
   if (CPU == "generic")
-    return ARM::ARMArchNames[static_cast<unsigned>(AK)].DefaultFPU;
-
-  return StringSwitch<ARM::FPUKind>(CPU)
-#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)           
\
-  .Case(NAME, DEFAULT_FPU)
-#include "llvm/TargetParser/ARMTargetParser.def"
-      .Default(ARM::FK_INVALID);
+    return ArchNames[static_cast<unsigned>(AK)].value().DefaultFPU;
+  for (const auto &C : CPUNames) {
+    if (C.name() == CPU)
+      return C.value().DefaultFPU;
+  }
+  return ARM::FK_INVALID;
 }
 
 uint64_t ARM::getDefaultExtensions(StringRef CPU, ARM::ArchKind AK) {
   if (CPU == "generic")
-    return ARM::ARMArchNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
-
-  return StringSwitch<uint64_t>(CPU)
-#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)           
\
-  .Case(NAME,                                                                  
\
-        ARMArchNames[static_cast<unsigned>(ArchKind::ID)].ArchBaseExtensions | 
\
-            DEFAULT_EXT)
-#include "llvm/TargetParser/ARMTargetParser.def"
-  .Default(ARM::AEK_INVALID);
+    return ArchNames[static_cast<unsigned>(AK)].value().ArchBaseExtensions;
+  for (const auto &C : CPUNames) {
+    if (C.name() == CPU)
+      return ArchNames[static_cast<unsigned>(C.value().ArchID)]
+                 .value()
+                 .ArchBaseExtensions |
+             C.value().DefaultExtensions;
+  }
+  return ARM::AEK_INVALID;
 }
 
 bool ARM::getHWDivFeatures(uint64_t HWDivKind,
@@ -319,38 +392,37 @@ bool ARM::getExtensionFeatures(uint64_t Extensions,
   if (Extensions == AEK_INVALID)
     return false;
 
-  for (const auto &AE : ARCHExtNames) {
-    if ((Extensions & AE.ID) == AE.ID && !AE.Feature.empty())
-      Features.push_back(AE.Feature);
-    else if (!AE.NegFeature.empty())
-      Features.push_back(AE.NegFeature);
+  for (const auto &AE : ExtNames) {
+    if ((Extensions & AE.value()) == AE.value() && !AE.name(1).empty())
+      Features.push_back(AE.name(1));
+    else if (!AE.name(2).empty())
+      Features.push_back(AE.name(2));
   }
 
   return getHWDivFeatures(Extensions, Features);
 }
 
 StringRef ARM::getArchName(ARM::ArchKind AK) {
-  return ARMArchNames[static_cast<unsigned>(AK)].Name;
+  return ArchNames[static_cast<unsigned>(AK)].name(0);
 }
 
 StringRef ARM::getCPUAttr(ARM::ArchKind AK) {
-  return ARMArchNames[static_cast<unsigned>(AK)].CPUAttr;
+  return ArchNames[static_cast<unsigned>(AK)].name(1);
 }
 
 StringRef ARM::getSubArch(ARM::ArchKind AK) {
-  return ARMArchNames[static_cast<unsigned>(AK)].getSubArch();
+  // Return ArchFeature without the leading "+".
+  return ArchNames[static_cast<unsigned>(AK)].name(2).substr(1);
 }
 
 unsigned ARM::getArchAttr(ARM::ArchKind AK) {
-  return ARMArchNames[static_cast<unsigned>(AK)].ArchAttr;
+  return ArchNames[static_cast<unsigned>(AK)].value().ArchAttr;
 }
 
+EnumStrings<uint64_t, 3> ARM::getArchExts() { return EnumStrings(ExtNames); }
+
 StringRef ARM::getArchExtName(uint64_t ArchExtKind) {
-  for (const auto &AE : ARCHExtNames) {
-    if (ArchExtKind == AE.ID)
-      return AE.Name;
-  }
-  return StringRef();
+  return EnumStrings(ExtNames).toString(ArchExtKind);
 }
 
 static bool stripNegationPrefix(StringRef &Name) {
@@ -359,9 +431,9 @@ static bool stripNegationPrefix(StringRef &Name) {
 
 StringRef ARM::getArchExtFeature(StringRef ArchExt) {
   bool Negated = stripNegationPrefix(ArchExt);
-  for (const auto &AE : ARCHExtNames) {
-    if (!AE.Feature.empty() && ArchExt == AE.Name)
-      return StringRef(Negated ? AE.NegFeature : AE.Feature);
+  for (const auto &AE : ExtNames) {
+    if (!AE.name(1).empty() && ArchExt == AE.name())
+      return AE.name(Negated ? 2 : 1);
   }
 
   return StringRef();
@@ -371,7 +443,7 @@ static ARM::FPUKind findDoublePrecisionFPU(ARM::FPUKind 
InputFPUKind) {
   if (InputFPUKind == ARM::FK_INVALID || InputFPUKind == ARM::FK_NONE)
     return ARM::FK_INVALID;
 
-  const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind];
+  const FPUName &InputFPU = FPUNames[InputFPUKind].value();
 
   // If the input FPU already supports double-precision, then there
   // isn't any different FPU we can return here.
@@ -380,7 +452,8 @@ static ARM::FPUKind findDoublePrecisionFPU(ARM::FPUKind 
InputFPUKind) {
 
   // Otherwise, look for an FPU entry with all the same fields, except
   // that it supports double precision.
-  for (const ARM::FPUName &CandidateFPU : ARM::FPUNames) {
+  for (const auto &CandidateFPUEntry : FPUNames) {
+    const FPUName &CandidateFPU = CandidateFPUEntry.value();
     if (CandidateFPU.FPUVer == InputFPU.FPUVer &&
         CandidateFPU.NeonSupport == InputFPU.NeonSupport &&
         ARM::has32Regs(CandidateFPU.Restriction) ==
@@ -398,7 +471,7 @@ static ARM::FPUKind findSinglePrecisionFPU(ARM::FPUKind 
InputFPUKind) {
   if (InputFPUKind == ARM::FK_INVALID || InputFPUKind == ARM::FK_NONE)
     return ARM::FK_INVALID;
 
-  const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind];
+  const FPUName &InputFPU = FPUNames[InputFPUKind].value();
 
   // If the input FPU already is single-precision only, then there
   // isn't any different FPU we can return here.
@@ -409,10 +482,10 @@ static ARM::FPUKind findSinglePrecisionFPU(ARM::FPUKind 
InputFPUKind) {
   // and is not Double Precision. We want to allow for changing of
   // NEON Support and Restrictions so CPU's such as Cortex-R52 can
   // select between SP Only and Full DP modes.
-  for (const ARM::FPUName &CandidateFPU : ARM::FPUNames) {
-    if (CandidateFPU.FPUVer == InputFPU.FPUVer &&
-        !ARM::isDoublePrecision(CandidateFPU.Restriction)) {
-      return CandidateFPU.ID;
+  for (const auto &CandidateFPU : FPUNames) {
+    if (CandidateFPU.value().FPUVer == InputFPU.FPUVer &&
+        !ARM::isDoublePrecision(CandidateFPU.value().Restriction)) {
+      return CandidateFPU.value().ID;
     }
   }
 
@@ -432,13 +505,13 @@ bool ARM::appendArchExtFeatures(StringRef CPU, 
ARM::ArchKind AK,
   if (ID == AEK_INVALID)
     return false;
 
-  for (const auto &AE : ARCHExtNames) {
+  for (const auto &AE : ExtNames) {
     if (Negated) {
-      if ((AE.ID & ID) == ID && !AE.NegFeature.empty())
-        Features.push_back(AE.NegFeature);
+      if ((AE.value() & ID) == ID && !AE.name(2).empty())
+        Features.push_back(AE.name(2));
     } else {
-      if ((AE.ID & ID) == AE.ID && !AE.Feature.empty())
-        Features.push_back(AE.Feature);
+      if ((AE.value() & ID) == AE.value() && !AE.name(1).empty())
+        Features.push_back(AE.name(1));
     }
   }
 
@@ -497,8 +570,8 @@ StringRef ARM::getDefaultCPU(StringRef Arch) {
 
   // Look for multiple AKs to find the default for pair AK+Name.
   for (const auto &CPU : CPUNames) {
-    if (CPU.ArchID == AK && CPU.Default)
-      return CPU.Name;
+    if (CPU.value().ArchID == AK && CPU.value().Default)
+      return CPU.name();
   }
 
   // If we can't find a default then target the architecture instead
@@ -506,34 +579,42 @@ StringRef ARM::getDefaultCPU(StringRef Arch) {
 }
 
 uint64_t ARM::parseHWDiv(StringRef HWDiv) {
+  // List of HWDiv names (use getHWDivSynonym) and which architectural
+  // features they correspond to (use getHWDivFeatures).
+  constexpr EnumStringDef<uint64_t> HWDivNameDefs[] = {
+#define ARM_HW_DIV_NAME(NAME, ID) {{NAME}, ID},
+#include "llvm/TargetParser/ARMTargetParser.def"
+  };
+  static constexpr auto HWDivNames = BUILD_ENUM_STRINGS(HWDivNameDefs);
+
   StringRef Syn = getHWDivSynonym(HWDiv);
   for (const auto &D : HWDivNames) {
-    if (Syn == D.Name)
-      return D.ID;
+    if (Syn == D.name())
+      return D.value();
   }
   return AEK_INVALID;
 }
 
 uint64_t ARM::parseArchExt(StringRef ArchExt) {
-  for (const auto &A : ARCHExtNames) {
-    if (ArchExt == A.Name)
-      return A.ID;
+  for (const auto &A : ExtNames) {
+    if (ArchExt == A.name(0))
+      return A.value();
   }
   return AEK_INVALID;
 }
 
 ARM::ArchKind ARM::parseCPUArch(StringRef CPU) {
   for (const auto &C : CPUNames) {
-    if (CPU == C.Name)
-      return C.ArchID;
+    if (CPU == C.name())
+      return C.value().ArchID;
   }
   return ArchKind::INVALID;
 }
 
 void ARM::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
-  for (const auto &Arch : CPUNames) {
-    if (Arch.ArchID != ArchKind::INVALID)
-      Values.push_back(Arch.Name);
+  for (const auto &CPU : CPUNames) {
+    if (CPU.value().ArchID != ArchKind::INVALID)
+      Values.push_back(CPU.name());
   }
 }
 
@@ -671,17 +752,17 @@ void ARM::PrintSupportedExtensions(StringMap<StringRef> 
DescMap) {
   outs() << "All available -march extensions for ARM\n\n"
          << "    " << left_justify("Name", 20)
          << (DescMap.empty() ? "\n" : "Description\n");
-  for (const auto &Ext : ARCHExtNames) {
+  for (const auto &Ext : ExtNames) {
     // Extensions without a feature cannot be used with -march.
-    if (!Ext.Feature.empty()) {
-      std::string Description = DescMap[Ext.Name].str();
+    if (!Ext.name(1).empty()) {
+      std::string Description = DescMap[Ext.name(0)].str();
       // With SIMD, this links to the NEON feature, so the description should 
be
       // taken from here, as SIMD does not exist in TableGen.
-      if (Ext.Name == "simd")
+      if (Ext.name(0) == "simd")
         Description = DescMap["neon"].str();
       outs() << "    "
              << format(Description.empty() ? "%s\n" : "%-20s%s\n",
-                       Ext.Name.str().c_str(), Description.c_str());
+                       Ext.name().str().c_str(), Description.c_str());
     }
   }
 }
diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp 
b/llvm/unittests/TargetParser/TargetParserTest.cpp
index c91b6b3ac08d8..e019c6eb85c44 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -7,6 +7,7 @@
 
//===----------------------------------------------------------------------===//
 
 #include "llvm/TargetParser/TargetParser.h"
+#include "llvm/ADT/Enum.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringMap.h"
@@ -787,31 +788,31 @@ TEST(TargetParserTest, ARMFPURestriction) {
 }
 
 TEST(TargetParserTest, ARMExtensionFeatures) {
-  std::map<uint64_t, std::vector<StringRef>> Extensions;
+  std::vector<std::tuple<ARM::ArchExtKind, StringRef, StringRef>> Extensions;
 
-  for (auto &Ext : ARM::ARCHExtNames) {
-    if (!Ext.Feature.empty() && !Ext.NegFeature.empty())
-      Extensions[Ext.ID] = {Ext.Feature, Ext.NegFeature};
+  for (auto &Ext : ARM::getArchExts()) {
+    if (!Ext.name(1).empty() && !Ext.name(2).empty())
+      Extensions.emplace_back(Ext.value(), Ext.name(1), Ext.name(2));
   }
 
-  Extensions[ARM::AEK_HWDIVARM] = {"+hwdiv-arm", "-hwdiv-arm"};
-  Extensions[ARM::AEK_HWDIVTHUMB] = {"+hwdiv", "-hwdiv"};
+  Extensions.emplace_back(ARM::AEK_HWDIVARM, "+hwdiv-arm", "-hwdiv-arm");
+  Extensions.emplace_back(ARM::AEK_HWDIVTHUMB, "+hwdiv", "-hwdiv");
 
   std::vector<StringRef> Features;
 
   EXPECT_FALSE(ARM::getExtensionFeatures(ARM::AEK_INVALID, Features));
 
-  for (auto &E : Extensions) {
+  for (auto &[ExtID, PosFeature, NegFeature] : Extensions) {
     // test +extension
     Features.clear();
-    ARM::getExtensionFeatures(E.first, Features);
-    EXPECT_TRUE(llvm::is_contained(Features, E.second.at(0)));
+    ARM::getExtensionFeatures(ExtID, Features);
+    EXPECT_TRUE(llvm::is_contained(Features, PosFeature));
     EXPECT_EQ(Extensions.size(), Features.size());
 
     // test -extension
     Features.clear();
-    ARM::getExtensionFeatures(~E.first, Features);
-    EXPECT_TRUE(llvm::is_contained(Features, E.second.at(1)));
+    ARM::getExtensionFeatures(~ExtID, Features);
+    EXPECT_TRUE(llvm::is_contained(Features, NegFeature));
     EXPECT_EQ(Extensions.size(), Features.size());
   }
 }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to