Skip to content

Commit 2b3e07f

Browse files
authored
[utils][TableGen] Unify converting names to upper-camel case (#141762)
There were 3 different functions in DirectiveEmitter.cpp doing essentially the same thing: taking a name separated with _ or whitepace, and converting it to the upper-camel case. Extract that into a single function that can handle different sets of separators.
1 parent ef60ee6 commit 2b3e07f

File tree

2 files changed

+37
-45
lines changed

2 files changed

+37
-45
lines changed

llvm/include/llvm/TableGen/DirectiveEmitter.h

Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,43 @@ class BaseRecord {
113113

114114
// Returns the name of the directive formatted for output. Whitespace are
115115
// replaced with underscores.
116-
static std::string formatName(StringRef Name) {
116+
static std::string getSnakeName(StringRef Name) {
117117
std::string N = Name.str();
118118
llvm::replace(N, ' ', '_');
119119
return N;
120120
}
121121

122+
// Take a string Name with sub-words separated with characters from Sep,
123+
// and return a string with each of the sub-words capitalized, and the
124+
// separators removed, e.g.
125+
// Name = "some_directive^name", Sep = "_^" -> "SomeDirectiveName".
126+
static std::string getUpperCamelName(StringRef Name, StringRef Sep) {
127+
std::string Camel = Name.str();
128+
// Convert to uppercase
129+
bool Cap = true;
130+
llvm::transform(Camel, Camel.begin(), [&](unsigned char C) {
131+
if (Sep.contains(C)) {
132+
assert(!Cap && "No initial or repeated separators");
133+
Cap = true;
134+
} else if (Cap) {
135+
C = llvm::toUpper(C);
136+
Cap = false;
137+
}
138+
return C;
139+
});
140+
size_t Out = 0;
141+
// Remove separators
142+
for (size_t In = 0, End = Camel.size(); In != End; ++In) {
143+
unsigned char C = Camel[In];
144+
if (!Sep.contains(C))
145+
Camel[Out++] = C;
146+
}
147+
Camel.resize(Out);
148+
return Camel;
149+
}
150+
122151
std::string getFormattedName() const {
123-
return formatName(Def->getValueAsString("name"));
152+
return getSnakeName(Def->getValueAsString("name"));
124153
}
125154

126155
bool isDefault() const { return Def->getValueAsBit("isDefault"); }
@@ -172,26 +201,13 @@ class Directive : public BaseRecord {
172201

173202
// Clang uses a different format for names of its directives enum.
174203
std::string getClangAccSpelling() const {
175-
std::string Name = Def->getValueAsString("name").str();
204+
StringRef Name = Def->getValueAsString("name");
176205

177206
// Clang calls the 'unknown' value 'invalid'.
178207
if (Name == "unknown")
179208
return "Invalid";
180209

181-
// Clang entries all start with a capital letter, so apply that.
182-
Name[0] = std::toupper(Name[0]);
183-
// Additionally, spaces/underscores are handled by capitalizing the next
184-
// letter of the name and removing the space/underscore.
185-
for (unsigned I = 0; I < Name.size(); ++I) {
186-
if (Name[I] == ' ' || Name[I] == '_') {
187-
Name.erase(I, 1);
188-
assert(Name[I] != ' ' && Name[I] != '_' &&
189-
"No double spaces/underscores");
190-
Name[I] = std::toupper(Name[I]);
191-
}
192-
}
193-
194-
return Name;
210+
return BaseRecord::getUpperCamelName(Name, " _");
195211
}
196212
};
197213

@@ -218,19 +234,7 @@ class Clause : public BaseRecord {
218234
// num_threads -> NumThreads
219235
std::string getFormattedParserClassName() const {
220236
StringRef Name = Def->getValueAsString("name");
221-
std::string N = Name.str();
222-
bool Cap = true;
223-
llvm::transform(N, N.begin(), [&Cap](unsigned char C) {
224-
if (Cap == true) {
225-
C = toUpper(C);
226-
Cap = false;
227-
} else if (C == '_') {
228-
Cap = true;
229-
}
230-
return C;
231-
});
232-
erase(N, '_');
233-
return N;
237+
return BaseRecord::getUpperCamelName(Name, "_");
234238
}
235239

236240
// Clang uses a different format for names of its clause enum, which can be
@@ -241,20 +245,8 @@ class Clause : public BaseRecord {
241245
!ClangSpelling.empty())
242246
return ClangSpelling.str();
243247

244-
std::string Name = Def->getValueAsString("name").str();
245-
// Clang entries all start with a capital letter, so apply that.
246-
Name[0] = std::toupper(Name[0]);
247-
// Additionally, underscores are handled by capitalizing the next letter of
248-
// the name and removing the underscore.
249-
for (unsigned I = 0; I < Name.size(); ++I) {
250-
if (Name[I] == '_') {
251-
Name.erase(I, 1);
252-
assert(Name[I] != '_' && "No double underscores");
253-
Name[I] = std::toupper(Name[I]);
254-
}
255-
}
256-
257-
return Name;
248+
StringRef Name = Def->getValueAsString("name");
249+
return BaseRecord::getUpperCamelName(Name, "_");
258250
}
259251

260252
// Optional field.

llvm/utils/TableGen/Basic/DirectiveEmitter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ static void generateGetDirectiveLanguages(const DirectiveLanguage &DirLang,
839839
D.getSourceLanguages(), OS,
840840
[&](const Record *L) {
841841
StringRef N = L->getValueAsString("name");
842-
OS << "SourceLanguage::" << BaseRecord::formatName(N);
842+
OS << "SourceLanguage::" << BaseRecord::getSnakeName(N);
843843
},
844844
" | ");
845845
OS << ";\n";

0 commit comments

Comments
 (0)