19
19
#include "llvm/ADT/ArrayRef.h"
20
20
#include "llvm/ADT/STLExtras.h"
21
21
#include "llvm/ADT/StringRef.h"
22
+ #include "llvm/ADT/StringSet.h"
22
23
#include "llvm/Frontend/OpenMP/OMP.h"
23
24
24
25
// OpenMP Directives and Clauses
@@ -104,8 +105,13 @@ struct OmpDirectiveNameParser {
104
105
using Token = TokenStringMatch<false, false>;
105
106
106
107
std::optional<resultType> Parse(ParseState &state) const {
108
+ if (state.BytesRemaining() == 0) {
109
+ return std::nullopt;
110
+ }
107
111
auto begin{state.GetLocation()};
108
- for (const NameWithId &nid : directives()) {
112
+ char next{static_cast<char>(std::tolower(*begin))};
113
+
114
+ for (const NameWithId &nid : directives_starting_with(next)) {
109
115
if (attempt(Token(nid.first.data())).Parse(state)) {
110
116
OmpDirectiveName n;
111
117
n.v = nid.second;
@@ -118,30 +124,46 @@ struct OmpDirectiveNameParser {
118
124
119
125
private:
120
126
using NameWithId = std::pair<std::string, llvm::omp::Directive>;
127
+ using ConstIterator = std::vector<NameWithId>::const_iterator;
121
128
122
- llvm::iterator_range<const NameWithId *> directives() const;
123
- void initTokens(NameWithId *) const;
129
+ llvm::iterator_range<ConstIterator> directives_starting_with(
130
+ char initial) const;
131
+ void initTokens(std::vector<NameWithId>[]) const;
124
132
};
125
133
126
- llvm::iterator_range<const OmpDirectiveNameParser::NameWithId *>
127
- OmpDirectiveNameParser::directives() const {
128
- static NameWithId table[llvm::omp::Directive_enumSize];
134
+ llvm::iterator_range<OmpDirectiveNameParser::ConstIterator>
135
+ OmpDirectiveNameParser::directives_starting_with(char initial) const {
136
+ static const std::vector<NameWithId> empty{};
137
+ if (initial < 'a' || initial > 'z') {
138
+ return llvm::make_range(std::cbegin(empty), std::cend(empty));
139
+ }
140
+
141
+ static std::vector<NameWithId> table['z' - 'a' + 1];
129
142
[[maybe_unused]] static bool init = (initTokens(table), true);
130
- return llvm::make_range(std::cbegin(table), std::cend(table));
143
+
144
+ int index = initial - 'a';
145
+ return llvm::make_range(std::cbegin(table[index]), std::cend(table[index]));
131
146
}
132
147
133
- void OmpDirectiveNameParser::initTokens(NameWithId * table) const {
148
+ void OmpDirectiveNameParser::initTokens(std::vector< NameWithId> table[] ) const {
134
149
for (size_t i{0}, e{llvm::omp::Directive_enumSize}; i != e; ++i) {
150
+ llvm::StringSet spellings;
135
151
auto id{static_cast<llvm::omp::Directive>(i)};
136
- llvm::StringRef name{
137
- llvm::omp::getOpenMPDirectiveName(id, llvm::omp::FallbackVersion)};
138
- table[i] = std::make_pair(name.str(), id);
152
+ for (unsigned version : llvm::omp::getOpenMPVersions()) {
153
+ spellings.insert(llvm::omp::getOpenMPDirectiveName(id, version));
154
+ }
155
+ for (auto &[name, _] : spellings) {
156
+ char initial{static_cast<char>(std::tolower(name.front()))};
157
+ table[initial - 'a'].emplace_back(name.str(), id);
158
+ }
139
159
}
140
160
// Sort the table with respect to the directive name length in a descending
141
161
// order. This is to make sure that longer names are tried first, before
142
162
// any potential prefix (e.g. "target update" before "target").
143
- std::sort(table, table + llvm::omp::Directive_enumSize,
144
- [](auto &a, auto &b) { return a.first.size() > b.first.size(); });
163
+ for (int initial{'a'}; initial != 'z' + 1; ++initial) {
164
+ llvm::stable_sort(table[initial - 'a'],
165
+ [](auto &a, auto &b) { return a.first.size() > b.first.size(); });
166
+ }
145
167
}
146
168
147
169
// --- Modifier helpers -----------------------------------------------
0 commit comments