@@ -77,6 +77,19 @@ static std::string getIdentifierName(const Record *Rec, StringRef Prefix) {
77
77
return Prefix.str () + BaseRecord (Rec).getFormattedName ();
78
78
}
79
79
80
+ using RecordWithSpelling = std::pair<const Record *, Spelling::Value>;
81
+
82
+ static std::vector<RecordWithSpelling>
83
+ getSpellings (ArrayRef<const Record *> Records) {
84
+ std::vector<RecordWithSpelling> List;
85
+ for (const Record *R : Records) {
86
+ Clause C (R);
87
+ llvm::transform (C.getSpellings (), std::back_inserter (List),
88
+ [R](Spelling::Value V) { return std::make_pair (R, V); });
89
+ }
90
+ return List;
91
+ }
92
+
80
93
static void generateEnumExports (ArrayRef<const Record *> Records,
81
94
raw_ostream &OS, StringRef Enum,
82
95
StringRef Prefix) {
@@ -270,6 +283,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
270
283
OS << " #include \" llvm/ADT/BitmaskEnum.h\"\n " ;
271
284
272
285
OS << " #include \" llvm/ADT/StringRef.h\"\n " ;
286
+ OS << " #include \" llvm/Frontend/Directive/Spelling.h\"\n " ;
273
287
OS << " #include \" llvm/Support/Compiler.h\"\n " ;
274
288
OS << " #include <cstddef>\n " ; // for size_t
275
289
OS << " #include <utility>\n " ; // for std::pair
@@ -285,13 +299,6 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
285
299
if (DirLang.hasEnableBitmaskEnumInNamespace ())
286
300
OS << " \n LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n " ;
287
301
288
- #define AS_STRING_HELPER_TO_GET_THE_ARGUMENT_MACRO_EXPANDED (x ) #x
289
- #define AS_STRING (x ) AS_STRING_HELPER_TO_GET_THE_ARGUMENT_MACRO_EXPANDED(x)
290
- OS << " \n " ;
291
- OS << AS_STRING (STRUCT_VERSION_RANGE) << " ;\n " ;
292
- #undef AS_STRING
293
- #undef AS_STRING_HELPER_TO_GET_THE_ARGUMENT_MACRO_EXPANDED
294
-
295
302
// Emit Directive associations
296
303
std::vector<const Record *> Associations;
297
304
copy_if (DirLang.getAssociations (), std::back_inserter (Associations),
@@ -324,7 +331,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
324
331
OS << " \n " ;
325
332
OS << " // Enumeration helper functions\n " ;
326
333
327
- OS << " LLVM_ABI std::pair<Directive, VersionRange> get" << Lang
334
+ OS << " LLVM_ABI std::pair<Directive, directive:: VersionRange> get" << Lang
328
335
<< " DirectiveKindAndVersions(StringRef Str);\n " ;
329
336
330
337
OS << " inline Directive get" << Lang << " DirectiveKind(StringRef Str) {\n " ;
@@ -336,7 +343,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
336
343
<< " DirectiveName(Directive D, unsigned Ver = 0);\n " ;
337
344
OS << " \n " ;
338
345
339
- OS << " LLVM_ABI std::pair<Clause, VersionRange> get" << Lang
346
+ OS << " LLVM_ABI std::pair<Clause, directive:: VersionRange> get" << Lang
340
347
<< " ClauseKindAndVersions(StringRef Str);\n " ;
341
348
OS << " \n " ;
342
349
@@ -373,6 +380,33 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
373
380
OS << " #endif // LLVM_" << Lang << " _INC\n " ;
374
381
}
375
382
383
+ // Given a list of spellings (for a given clause/directive), order them
384
+ // in a way that allows the use of binary search to locate a spelling
385
+ // for a specified version.
386
+ static std::vector<Spelling::Value>
387
+ orderSpellings (ArrayRef<Spelling::Value> Spellings) {
388
+ std::vector<Spelling::Value> List (Spellings.begin (), Spellings.end ());
389
+
390
+ // There are two intertwined orderings: (1) the order between spellings
391
+ // (used here), and (2) the order between a spelling and a version (used
392
+ // at runtime).
393
+ // Define order (2) as such that the first A that is not less than V
394
+ // will be the selected spelling given V. Specifically,
395
+ // V <(2) A <=> V < A.Min
396
+ // A <(2) V <=> A.Max < V
397
+ //
398
+ // The orders have to be compatible, i.e.
399
+ // A <(2) V and !(V <(2) B) => A <(1) B, and
400
+ // !(A <(2) v) and V <(2) B => A <(1) B
401
+ // In other words, the transitive closure of (2) must contain (1).
402
+ llvm::stable_sort (List,
403
+ [](const Spelling::Value &A, const Spelling::Value &B) {
404
+ return A.Versions < B.Versions ;
405
+ });
406
+
407
+ return List;
408
+ }
409
+
376
410
// Generate function implementation for get<Enum>Name(StringRef Str)
377
411
static void generateGetName (ArrayRef<const Record *> Records, raw_ostream &OS,
378
412
StringRef Enum, const DirectiveLanguage &DirLang,
@@ -381,14 +415,31 @@ static void generateGetName(ArrayRef<const Record *> Records, raw_ostream &OS,
381
415
std::string Qual = getQualifier (DirLang);
382
416
OS << " \n " ;
383
417
OS << " llvm::StringRef " << Qual << " get" << Lang << Enum << " Name(" << Qual
384
- << Enum << " Kind, unsigned) {\n " ;
418
+ << Enum << " Kind, unsigned Version ) {\n " ;
385
419
OS << " switch (Kind) {\n " ;
386
420
for (const Record *R : Records) {
387
- OS << " case " << getIdentifierName (R, Prefix) << " :\n " ;
388
- // FIXME: This will need to recognize different spellings for different
389
- // versions.
390
- OS << " return \" " << BaseRecord (R).getSpellingForIdentifier ()
391
- << " \" ;\n " ;
421
+ BaseRecord Rec (R);
422
+ std::string Ident = getIdentifierName (R, Prefix);
423
+ OS << " case " << Ident << " :" ;
424
+ auto Spellings (orderSpellings (Rec.getSpellings ()));
425
+ assert (Spellings.size () != 0 && " No spellings for this item" );
426
+ if (Spellings.size () == 1 ) {
427
+ OS << " \n " ;
428
+ OS << " return \" " << Spellings.front ().Name << " \" ;\n " ;
429
+ } else {
430
+ OS << " {\n " ;
431
+ std::string SpellingsName = Ident + " _spellings" ;
432
+ OS << " static const llvm::directive::Spelling " << SpellingsName
433
+ << " [] = {\n " ;
434
+ for (auto &S : Spellings) {
435
+ OS << " {\" " << S.Name << " \" , {" << S.Versions .Min << " , "
436
+ << S.Versions .Max << " }},\n " ;
437
+ }
438
+ OS << " };\n " ;
439
+ OS << " return llvm::directive::FindName(" << SpellingsName
440
+ << " , Version);\n " ;
441
+ OS << " }\n " ;
442
+ }
392
443
}
393
444
OS << " }\n " ; // switch
394
445
OS << " llvm_unreachable(\" Invalid " << Lang << " " << Enum << " kind\" );\n " ;
@@ -415,23 +466,29 @@ static void generateGetKind(ArrayRef<const Record *> Records, raw_ostream &OS,
415
466
// std::pair<<Enum>, VersionRange>
416
467
// get<DirLang><Enum>KindAndVersions(StringRef Str);
417
468
OS << " \n " ;
418
- OS << " std::pair<" << Qual << Enum << " , " << Qual << " VersionRange> " << Qual
419
- << " get" << DirLang.getName () << Enum
469
+ OS << " std::pair<" << Qual << Enum << " , llvm::directive:: VersionRange> "
470
+ << Qual << " get" << DirLang.getName () << Enum
420
471
<< " KindAndVersions(llvm::StringRef Str) {\n " ;
421
- OS << " VersionRange All{}; // Default-initialized to \" all-versions\"\n " ;
472
+ OS << " directive::VersionRange All; // Default-initialized to \" all "
473
+ " versions\"\n " ;
422
474
OS << " return StringSwitch<std::pair<" << Enum << " , "
423
- << " VersionRange>>(Str)\n " ;
475
+ << " directive::VersionRange>>(Str)\n " ;
476
+
477
+ directive::VersionRange All;
424
478
425
479
for (const Record *R : Records) {
426
480
BaseRecord Rec (R);
427
- // FIXME: This will need to recognize different spellings for different
428
- // versions.
429
- StringRef Name = Rec.getSpellingForIdentifier ();
430
- if (ImplicitAsUnknown && R->getValueAsBit (" isImplicit" )) {
431
- OS << " .Case(\" " << Name << " \" , {" << DefaultName << " , All})\n " ;
432
- } else {
433
- OS << " .Case(\" " << Name << " \" , {"
434
- << getIdentifierName (R, Prefix) << " , All})\n " ;
481
+ std::string Ident = ImplicitAsUnknown && R->getValueAsBit (" isImplicit" )
482
+ ? DefaultName
483
+ : getIdentifierName (R, Prefix);
484
+
485
+ for (auto &[Name, Versions] : Rec.getSpellings ()) {
486
+ OS << " .Case(\" " << Name << " \" , {" << Ident << " , " ;
487
+ if (Versions.Min == All.Min && Versions.Max == All.Max ) {
488
+ OS << " All})\n " ;
489
+ } else {
490
+ OS << " {" << Versions.Min << " , " << Versions.Max << " }})\n " ;
491
+ }
435
492
}
436
493
}
437
494
OS << " .Default({" << DefaultName << " , All});\n " ;
@@ -1144,47 +1201,29 @@ static void generateFlangClauseParserKindMap(const DirectiveLanguage &DirLang,
1144
1201
<< " Parser clause\" );\n " ;
1145
1202
}
1146
1203
1147
- using RecordWithText = std::pair<const Record *, StringRef>;
1148
-
1149
- static bool compareRecordText (const RecordWithText &A,
1150
- const RecordWithText &B) {
1151
- return A.second > B.second ;
1152
- }
1153
-
1154
- static std::vector<RecordWithText>
1155
- getSpellingTexts (ArrayRef<const Record *> Records) {
1156
- std::vector<RecordWithText> List;
1157
- for (const Record *R : Records) {
1158
- Clause C (R);
1159
- llvm::transform (
1160
- C.getSpellings (), std::back_inserter (List),
1161
- [R](Spelling::Value V) { return std::make_pair (R, V.first ); });
1162
- }
1163
- return List;
1164
- }
1165
-
1166
1204
// Generate the parser for the clauses.
1167
1205
static void generateFlangClausesParser (const DirectiveLanguage &DirLang,
1168
1206
raw_ostream &OS) {
1169
1207
std::vector<const Record *> Clauses = DirLang.getClauses ();
1170
1208
// Sort clauses in the reverse alphabetical order with respect to their
1171
1209
// names and aliases, so that longer names are tried before shorter ones.
1172
- std::vector<std::pair<const Record *, StringRef>> Names =
1173
- getSpellingTexts (Clauses);
1174
- llvm::sort (Names, compareRecordText);
1210
+ std::vector<RecordWithSpelling> Names = getSpellings (Clauses);
1211
+ llvm::sort (Names, [](const auto &A, const auto &B) {
1212
+ return A.second .Name > B.second .Name ;
1213
+ });
1175
1214
IfDefScope Scope (" GEN_FLANG_CLAUSES_PARSER" , OS);
1176
1215
StringRef Base = DirLang.getFlangClauseBaseClass ();
1177
1216
1178
1217
unsigned LastIndex = Names.size () - 1 ;
1179
1218
OS << " \n " ;
1180
1219
OS << " TYPE_PARSER(\n " ;
1181
- for (auto [Index, RecTxt ] : llvm::enumerate (Names)) {
1182
- auto [R, N ] = RecTxt ;
1220
+ for (auto [Index, RecSp ] : llvm::enumerate (Names)) {
1221
+ auto [R, S ] = RecSp ;
1183
1222
Clause C (R);
1184
1223
1185
1224
StringRef FlangClass = C.getFlangClass ();
1186
- OS << " \" " << N << " \" >> construct<" << Base << " >(construct<" << Base
1187
- << " ::" << C.getFormattedParserClassName () << " >(" ;
1225
+ OS << " \" " << S. Name << " \" >> construct<" << Base << " >(construct<"
1226
+ << Base << " ::" << C.getFormattedParserClassName () << " >(" ;
1188
1227
if (FlangClass.empty ()) {
1189
1228
OS << " ))" ;
1190
1229
if (Index != LastIndex)
@@ -1337,6 +1376,7 @@ void emitDirectivesBasicImpl(const DirectiveLanguage &DirLang,
1337
1376
StringRef CPrefix = DirLang.getClausePrefix ();
1338
1377
1339
1378
OS << " \n " ;
1379
+ OS << " #include \" llvm/Frontend/Directive/Spelling.h\"\n " ;
1340
1380
OS << " #include \" llvm/Support/ErrorHandling.h\"\n " ;
1341
1381
OS << " #include <utility>\n " ;
1342
1382
0 commit comments