[flang-commits] [flang] 4d183b4 - Add constant time mapping from enumeration to string in ENUM_CLASS

via flang-commits flang-commits at lists.llvm.org
Thu Nov 10 08:58:31 PST 2022


Author: Renaud-K
Date: 2022-11-10T08:56:20-08:00
New Revision: 4d183b48c3b54e28533c97b53cfc2329f282b24e

URL: https://github.com/llvm/llvm-project/commit/4d183b48c3b54e28533c97b53cfc2329f282b24e
DIFF: https://github.com/llvm/llvm-project/commit/4d183b48c3b54e28533c97b53cfc2329f282b24e.diff

LOG: Add constant time mapping from enumeration to string in ENUM_CLASS
macro

Differential revision: https://reviews.llvm.org/D137577

Added: 
    

Modified: 
    flang/include/flang/Common/enum-set.h
    flang/include/flang/Common/idioms.h
    flang/lib/Common/idioms.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Common/enum-set.h b/flang/include/flang/Common/enum-set.h
index 5d2eda57aa819..3b0229104d9f3 100644
--- a/flang/include/flang/Common/enum-set.h
+++ b/flang/include/flang/Common/enum-set.h
@@ -206,7 +206,8 @@ template <typename ENUM, std::size_t BITS> class EnumSet {
   }
 
   template <typename STREAM>
-  STREAM &Dump(STREAM &o, std::string EnumToString(enumerationType)) const {
+  STREAM &Dump(
+      STREAM &o, const std::string &EnumToString(enumerationType)) const {
     char sep{'{'};
     IterateOverMembers([&](auto e) {
       o << sep << EnumToString(e);

diff  --git a/flang/include/flang/Common/idioms.h b/flang/include/flang/Common/idioms.h
index ac272d40fed67..e23ea2c9bda59 100644
--- a/flang/include/flang/Common/idioms.h
+++ b/flang/include/flang/Common/idioms.h
@@ -24,6 +24,7 @@
 #endif
 
 #include "visit.h"
+#include <array>
 #include <functional>
 #include <list>
 #include <memory>
@@ -110,12 +111,14 @@ template <typename... LAMBDAS> visitors(LAMBDAS... x) -> visitors<LAMBDAS...>;
   } \
   template <typename A> constexpr bool T{class_trait_ns_##T::trait_value<A>()};
 
-// Define enum class NAME with the given enumerators, a static
-// function EnumToString() that maps enumerators to std::string,
-// and a constant NAME_enumSize that captures the number of items
-// in the enum class.
+// Define enum class NAME with the given enumerators,
+// - a static function EnumToString() that maps enumerators to std::string,
+// - a constant NAME_enumSize that captures the number of items in the enum,
+// - a struct NAME_struct that implements a Meyers singleton to hold the mapping
+// from index to names
 
-std::string EnumIndexToString(int index, const char *names);
+void BuildIndexToString(
+    const char *commaSeparated, std::string enumNames[], int enumSize);
 
 template <typename A> struct ListItemCount {
   constexpr ListItemCount(std::initializer_list<A> list) : value{list.size()} {}
@@ -128,9 +131,24 @@ template <typename A> struct ListItemCount {
     enum { __VA_ARGS__ }; \
     return Fortran::common::ListItemCount{__VA_ARGS__}.value; \
   }()}; \
-  [[maybe_unused]] static inline std::string EnumToString(NAME e) { \
-    return Fortran::common::EnumIndexToString( \
-        static_cast<int>(e), #__VA_ARGS__); \
+  struct NAME##_struct { \
+    NAME##_struct(const NAME##_struct &) = delete; \
+    NAME##_struct &operator=(const NAME##_struct &) = delete; \
+    static NAME##_struct &instance() { \
+      static NAME##_struct s; \
+      return s; \
+    } \
+    std::array<std::string, NAME##_enumSize> _enumNames; \
+\
+  private: \
+    NAME##_struct() { \
+      Fortran::common::BuildIndexToString( \
+          #__VA_ARGS__, _enumNames.data(), NAME##_enumSize); \
+    } \
+    ~NAME##_struct() {} \
+  }; \
+  [[maybe_unused]] static inline const std::string &EnumToString(NAME e) { \
+    return NAME##_struct::instance()._enumNames[static_cast<int>(e)]; \
   }
 
 // Check that a pointer is non-null and dereference it

diff  --git a/flang/lib/Common/idioms.cpp b/flang/lib/Common/idioms.cpp
index cf6ff87b1bb17..95aebd1ec80a4 100644
--- a/flang/lib/Common/idioms.cpp
+++ b/flang/lib/Common/idioms.cpp
@@ -10,6 +10,7 @@
 #include <cstdarg>
 #include <cstdio>
 #include <cstdlib>
+#include <regex>
 
 namespace Fortran::common {
 
@@ -23,21 +24,22 @@ namespace Fortran::common {
   std::abort();
 }
 
-// Convert the int index of an enumerator to a string.
-// enumNames is a list of the names, separated by commas with optional spaces.
-// This is intended for use from the expansion of ENUM_CLASS.
-std::string EnumIndexToString(int index, const char *enumNames) {
-  const char *p{enumNames};
-  for (; index > 0; --index, ++p) {
-    for (; *p && *p != ','; ++p) {
-    }
-  }
-  for (; *p == ' '; ++p) {
-  }
-  CHECK(*p != '\0');
-  const char *q = p;
-  for (; *q && *q != ' ' && *q != ','; ++q) {
+// Converts the comma separated list of enumerators into tokens which are then
+// stored into the provided array of strings. This is intended for use from the
+// expansion of ENUM_CLASS.
+void BuildIndexToString(
+    const char *commaSeparated, std::string enumNames[], int enumSize) {
+  std::string input(commaSeparated);
+  std::regex reg("\\s*,\\s*");
+
+  std::sregex_token_iterator iter(input.begin(), input.end(), reg, -1);
+  std::sregex_token_iterator end;
+  int index = 0;
+  while (iter != end) {
+    enumNames[index] = *iter;
+    iter++;
+    index++;
   }
-  return std::string(p, q - p);
+  CHECK(index == enumSize);
 }
 } // namespace Fortran::common


        


More information about the flang-commits mailing list