Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/llvm/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/flang
diff options
context:
space:
mode:
authorRenaud-K <rkauffmann@nvidia.com>2022-11-07 22:02:57 +0300
committerRenaud-K <rkauffmann@nvidia.com>2022-11-10 19:56:20 +0300
commit4d183b48c3b54e28533c97b53cfc2329f282b24e (patch)
tree3f313a4ceb4469e09688cb393048fbae470e643f /flang
parent5f9e0491116e18b238f16091bc9a892cc6f7e64d (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.h3
-rw-r--r--flang/include/flang/Common/idioms.h34
-rw-r--r--flang/lib/Common/idioms.cpp32
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