diff options
author | Renaud-K <rkauffmann@nvidia.com> | 2022-11-07 22:02:57 +0300 |
---|---|---|
committer | Renaud-K <rkauffmann@nvidia.com> | 2022-11-10 19:56:20 +0300 |
commit | 4d183b48c3b54e28533c97b53cfc2329f282b24e (patch) | |
tree | 3f313a4ceb4469e09688cb393048fbae470e643f /flang | |
parent | 5f9e0491116e18b238f16091bc9a892cc6f7e64d (diff) |
Add constant time mapping from enumeration to string in ENUM_CLASS
macro
Differential revision: https://reviews.llvm.org/D137577
Diffstat (limited to 'flang')
-rw-r--r-- | flang/include/flang/Common/enum-set.h | 3 | ||||
-rw-r--r-- | flang/include/flang/Common/idioms.h | 34 | ||||
-rw-r--r-- | flang/lib/Common/idioms.cpp | 32 |
3 files changed, 45 insertions, 24 deletions
diff --git a/flang/include/flang/Common/enum-set.h b/flang/include/flang/Common/enum-set.h index 5d2eda57aa81..3b0229104d9f 100644 --- a/flang/include/flang/Common/enum-set.h +++ b/flang/include/flang/Common/enum-set.h @@ -206,7 +206,8 @@ public: } 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 ac272d40fed6..e23ea2c9bda5 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 cf6ff87b1bb1..95aebd1ec80a 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 |