-
Notifications
You must be signed in to change notification settings - Fork 14.1k
[utils][TableGen] Handle versions on clause/directive spellings #143021
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
In "get<lang>DirectiveName(Kind, Version)", return the spelling that corresponds to Version, and in "get<lang>DirectiveKindAndVersions(Name)" return the pair {Kind, VersionRange}, where VersionRange contains the minimum and the maximum versions that allow "Name" as a spelling. This applies to clauses as well. In general it applies to classes that have spellings (defined via TableGen class "Spelling"). Given a Kind and a Version, getting the corresponding spelling requires a runtime search (which can fail in a general case). To avoid generating the search function inline, a small additional component of llvm/Frontent was added: LLVMFrontendDirective. The corresponding header file also defines C++ classes "Spelling" and "VersionRange", which are used in TableGen/DirectiveEmitter as well. For background information see https://discourse.llvm.org/t/rfc-alternative-spellings-of-openmp-directives/85507
Recreation of accidentally destroyed #141766. |
@llvm/pr-subscribers-openacc @llvm/pr-subscribers-flang-openmp Author: Krzysztof Parzyszek (kparzysz) ChangesIn "get<lang>DirectiveName(Kind, Version)", return the spelling that corresponds to Version, and in "get<lang>DirectiveKindAndVersions(Name)" return the pair {Kind, VersionRange}, where VersionRange contains the minimum and the maximum versions that allow "Name" as a spelling. This applies to clauses as well. In general it applies to classes that have spellings (defined via TableGen class "Spelling"). Given a Kind and a Version, getting the corresponding spelling requires a runtime search (which can fail in a general case). To avoid generating the search function inline, a small additional component of llvm/Frontent was added: LLVMFrontendDirective. The corresponding header file also defines C++ classes "Spelling" and "VersionRange", which are used in TableGen/DirectiveEmitter as well. For background information see Patch is 26.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143021.diff 10 Files Affected:
diff --git a/llvm/include/llvm/Frontend/Directive/Spelling.h b/llvm/include/llvm/Frontend/Directive/Spelling.h
new file mode 100644
index 0000000000000..3ba0ae2296535
--- /dev/null
+++ b/llvm/include/llvm/Frontend/Directive/Spelling.h
@@ -0,0 +1,39 @@
+//===-- Spelling.h ------------------------------------------------ C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_FRONTEND_DIRECTIVE_SPELLING_H
+#define LLVM_FRONTEND_DIRECTIVE_SPELLING_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+
+#include <limits>
+
+namespace llvm::directive {
+
+struct VersionRange {
+ static constexpr int MaxValue = std::numeric_limits<int>::max();
+ int Min = 1;
+ int Max = MaxValue;
+};
+
+inline bool operator<(const VersionRange &A, const VersionRange &B) {
+ if (A.Min != B.Min)
+ return A.Min < B.Min;
+ return A.Max < B.Max;
+}
+
+struct Spelling {
+ StringRef Name;
+ VersionRange Versions;
+};
+
+StringRef FindName(llvm::iterator_range<const Spelling *>, unsigned Version);
+
+} // namespace llvm::directive
+
+#endif // LLVM_FRONTEND_DIRECTIVE_SPELLING_H
diff --git a/llvm/include/llvm/TableGen/DirectiveEmitter.h b/llvm/include/llvm/TableGen/DirectiveEmitter.h
index dc2f75083ec0d..a2256716a7c8b 100644
--- a/llvm/include/llvm/TableGen/DirectiveEmitter.h
+++ b/llvm/include/llvm/TableGen/DirectiveEmitter.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Frontend/Directive/Spelling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
@@ -113,29 +114,19 @@ class Versioned {
constexpr static int IntWidth = 8 * sizeof(int);
};
-// Range of specification versions: [Min, Max]
-// Default value: all possible versions.
-// This is the same structure as the one emitted into the generated sources.
-#define STRUCT_VERSION_RANGE \
- struct VersionRange { \
- int Min = 1; \
- int Max = 0x7fffffff; \
- }
-
-STRUCT_VERSION_RANGE;
-
class Spelling : public Versioned {
public:
- using Value = std::pair<StringRef, VersionRange>;
+ using Value = llvm::directive::Spelling;
Spelling(const Record *Def) : Def(Def) {}
StringRef getText() const { return Def->getValueAsString("spelling"); }
- VersionRange getVersions() const {
- return VersionRange{getMinVersion(Def), getMaxVersion(Def)};
+ llvm::directive::VersionRange getVersions() const {
+ return llvm::directive::VersionRange{getMinVersion(Def),
+ getMaxVersion(Def)};
}
- Value get() const { return std::make_pair(getText(), getVersions()); }
+ Value get() const { return Value{getText(), getVersions()}; }
private:
const Record *Def;
@@ -177,9 +168,9 @@ class BaseRecord {
// are added.
Spelling::Value Oldest{"not found", {/*Min=*/INT_MAX, 0}};
for (auto V : getSpellings())
- if (V.second.Min < Oldest.second.Min)
+ if (V.Versions.Min < Oldest.Versions.Min)
Oldest = V;
- return Oldest.first;
+ return Oldest.Name;
}
// Returns the name of the directive formatted for output. Whitespace are
diff --git a/llvm/lib/Frontend/CMakeLists.txt b/llvm/lib/Frontend/CMakeLists.txt
index b305ce7d771ce..3b31e6f8dec96 100644
--- a/llvm/lib/Frontend/CMakeLists.txt
+++ b/llvm/lib/Frontend/CMakeLists.txt
@@ -1,4 +1,5 @@
add_subdirectory(Atomic)
+add_subdirectory(Directive)
add_subdirectory(Driver)
add_subdirectory(HLSL)
add_subdirectory(OpenACC)
diff --git a/llvm/lib/Frontend/Directive/CMakeLists.txt b/llvm/lib/Frontend/Directive/CMakeLists.txt
new file mode 100644
index 0000000000000..a567e1affb171
--- /dev/null
+++ b/llvm/lib/Frontend/Directive/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_llvm_component_library(LLVMFrontendDirective
+ Spelling.cpp
+
+ LINK_COMPONENTS
+ Support
+)
diff --git a/llvm/lib/Frontend/Directive/Spelling.cpp b/llvm/lib/Frontend/Directive/Spelling.cpp
new file mode 100644
index 0000000000000..c808e625ee4fd
--- /dev/null
+++ b/llvm/lib/Frontend/Directive/Spelling.cpp
@@ -0,0 +1,31 @@
+//===-- Spelling.cpp ---------------------------------------------- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Frontend/Directive/Spelling.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MathExtras.h"
+
+#include <cassert>
+
+llvm::StringRef llvm::directive::FindName(
+ llvm::iterator_range<const llvm::directive::Spelling *> Range,
+ unsigned Version) {
+ assert(llvm::isInt<8 * sizeof(int)>(Version) && "Version value out of range");
+
+ int V = Version;
+ Spelling Tmp{StringRef(), {V, V}};
+ auto F =
+ llvm::lower_bound(Range, Tmp, [](const Spelling &A, const Spelling &B) {
+ return A.Versions < B.Versions;
+ });
+ if (F != Range.end())
+ return F->Name;
+ return StringRef();
+}
diff --git a/llvm/lib/Frontend/OpenACC/CMakeLists.txt b/llvm/lib/Frontend/OpenACC/CMakeLists.txt
index f352014978690..4664b71407c48 100644
--- a/llvm/lib/Frontend/OpenACC/CMakeLists.txt
+++ b/llvm/lib/Frontend/OpenACC/CMakeLists.txt
@@ -9,5 +9,5 @@ add_llvm_component_library(LLVMFrontendOpenACC
acc_gen
)
-target_link_libraries(LLVMFrontendOpenACC LLVMSupport)
+target_link_libraries(LLVMFrontendOpenACC LLVMSupport LLVMFrontendDirective)
diff --git a/llvm/lib/Frontend/OpenMP/CMakeLists.txt b/llvm/lib/Frontend/OpenMP/CMakeLists.txt
index 35c607866a94e..5bf15ca3a8991 100644
--- a/llvm/lib/Frontend/OpenMP/CMakeLists.txt
+++ b/llvm/lib/Frontend/OpenMP/CMakeLists.txt
@@ -23,4 +23,5 @@ add_llvm_component_library(LLVMFrontendOpenMP
BitReader
FrontendOffloading
FrontendAtomic
+ FrontendDirective
)
diff --git a/llvm/test/TableGen/directive1.td b/llvm/test/TableGen/directive1.td
index 8196a30d03df4..1c8da26f50f4b 100644
--- a/llvm/test/TableGen/directive1.td
+++ b/llvm/test/TableGen/directive1.td
@@ -54,6 +54,7 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-NEXT: #include "llvm/ADT/ArrayRef.h"
// CHECK-NEXT: #include "llvm/ADT/BitmaskEnum.h"
// CHECK-NEXT: #include "llvm/ADT/StringRef.h"
+// CHECK-NEXT: #include "llvm/Frontend/Directive/Spelling.h"
// CHECK-NEXT: #include "llvm/Support/Compiler.h"
// CHECK-NEXT: #include <cstddef>
// CHECK-NEXT: #include <utility>
@@ -63,8 +64,6 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-EMPTY:
// CHECK-NEXT: LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
// CHECK-EMPTY:
-// CHECK-NEXT: struct VersionRange { int Min = 1; int Max = 0x7fffffff; };
-// CHECK-EMPTY:
// CHECK-NEXT: enum class Association {
// CHECK-NEXT: Block,
// CHECK-NEXT: Declaration,
@@ -126,14 +125,14 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-NEXT: constexpr auto TDLCV_valc = AKind::TDLCV_valc;
// CHECK-EMPTY:
// CHECK-NEXT: // Enumeration helper functions
-// CHECK-NEXT: LLVM_ABI std::pair<Directive, VersionRange> getTdlDirectiveKindAndVersions(StringRef Str);
+// CHECK-NEXT: LLVM_ABI std::pair<Directive, directive::VersionRange> getTdlDirectiveKindAndVersions(StringRef Str);
// CHECK-NEXT: inline Directive getTdlDirectiveKind(StringRef Str) {
// CHECK-NEXT: return getTdlDirectiveKindAndVersions(Str).first;
// CHECK-NEXT: }
// CHECK-EMPTY:
// CHECK-NEXT: LLVM_ABI StringRef getTdlDirectiveName(Directive D, unsigned Ver = 0);
// CHECK-EMPTY:
-// CHECK-NEXT: LLVM_ABI std::pair<Clause, VersionRange> getTdlClauseKindAndVersions(StringRef Str);
+// CHECK-NEXT: LLVM_ABI std::pair<Clause, directive::VersionRange> getTdlClauseKindAndVersions(StringRef Str);
// CHECK-EMPTY:
// CHECK-NEXT: inline Clause getTdlClauseKind(StringRef Str) {
// CHECK-NEXT: return getTdlClauseKindAndVersions(Str).first;
@@ -320,17 +319,18 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// IMPL: #ifdef GEN_DIRECTIVES_IMPL
// IMPL-NEXT: #undef GEN_DIRECTIVES_IMPL
// IMPL-EMPTY:
+// IMPL-NEXT: #include "llvm/Frontend/Directive/Spelling.h"
// IMPL-NEXT: #include "llvm/Support/ErrorHandling.h"
// IMPL-NEXT: #include <utility>
// IMPL-EMPTY:
-// IMPL-NEXT: std::pair<llvm::tdl::Directive, llvm::tdl::VersionRange> llvm::tdl::getTdlDirectiveKindAndVersions(llvm::StringRef Str) {
-// IMPL-NEXT: VersionRange All{}; // Default-initialized to "all-versions"
-// IMPL-NEXT: return StringSwitch<std::pair<Directive, VersionRange>>(Str)
+// IMPL-NEXT: std::pair<llvm::tdl::Directive, llvm::directive::VersionRange> llvm::tdl::getTdlDirectiveKindAndVersions(llvm::StringRef Str) {
+// IMPL-NEXT: directive::VersionRange All; // Default-initialized to "all versions"
+// IMPL-NEXT: return StringSwitch<std::pair<Directive, directive::VersionRange>>(Str)
// IMPL-NEXT: .Case("dira", {TDLD_dira, All})
// IMPL-NEXT: .Default({TDLD_dira, All});
// IMPL-NEXT: }
// IMPL-EMPTY:
-// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlDirectiveName(llvm::tdl::Directive Kind, unsigned) {
+// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlDirectiveName(llvm::tdl::Directive Kind, unsigned Version) {
// IMPL-NEXT: switch (Kind) {
// IMPL-NEXT: case TDLD_dira:
// IMPL-NEXT: return "dira";
@@ -338,23 +338,29 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// IMPL-NEXT: llvm_unreachable("Invalid Tdl Directive kind");
// IMPL-NEXT: }
// IMPL-EMPTY:
-// IMPL-NEXT: std::pair<llvm::tdl::Clause, llvm::tdl::VersionRange> llvm::tdl::getTdlClauseKindAndVersions(llvm::StringRef Str) {
-// IMPL-NEXT: VersionRange All{}; // Default-initialized to "all-versions"
-// IMPL-NEXT: return StringSwitch<std::pair<Clause, VersionRange>>(Str)
+// IMPL-NEXT: std::pair<llvm::tdl::Clause, llvm::directive::VersionRange> llvm::tdl::getTdlClauseKindAndVersions(llvm::StringRef Str) {
+// IMPL-NEXT: directive::VersionRange All; // Default-initialized to "all versions"
+// IMPL-NEXT: return StringSwitch<std::pair<Clause, directive::VersionRange>>(Str)
// IMPL-NEXT: .Case("clausea", {TDLC_clausea, All})
// IMPL-NEXT: .Case("clauseb", {TDLC_clauseb, All})
// IMPL-NEXT: .Case("clausec", {TDLC_clausec, All})
+// IMPL-NEXT: .Case("ccccccc", {TDLC_clausec, All})
// IMPL-NEXT: .Default({TDLC_clauseb, All});
// IMPL-NEXT: }
// IMPL-EMPTY:
-// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlClauseName(llvm::tdl::Clause Kind, unsigned) {
+// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlClauseName(llvm::tdl::Clause Kind, unsigned Version) {
// IMPL-NEXT: switch (Kind) {
// IMPL-NEXT: case TDLC_clausea:
// IMPL-NEXT: return "clausea";
// IMPL-NEXT: case TDLC_clauseb:
// IMPL-NEXT: return "clauseb";
-// IMPL-NEXT: case TDLC_clausec:
-// IMPL-NEXT: return "clausec";
+// IMPL-NEXT: case TDLC_clausec: {
+// IMPL-NEXT: static const llvm::directive::Spelling TDLC_clausec_spellings[] = {
+// IMPL-NEXT: {"clausec", {1, 2147483647}},
+// IMPL-NEXT: {"ccccccc", {1, 2147483647}},
+// IMPL-NEXT: };
+// IMPL-NEXT: return llvm::directive::FindName(TDLC_clausec_spellings, Version);
+// IMPL-NEXT: }
// IMPL-NEXT: }
// IMPL-NEXT: llvm_unreachable("Invalid Tdl Clause kind");
// IMPL-NEXT: }
diff --git a/llvm/test/TableGen/directive2.td b/llvm/test/TableGen/directive2.td
index ead6aa2637b76..3a64bb3900a31 100644
--- a/llvm/test/TableGen/directive2.td
+++ b/llvm/test/TableGen/directive2.td
@@ -47,6 +47,7 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-EMPTY:
// CHECK-NEXT: #include "llvm/ADT/ArrayRef.h"
// CHECK-NEXT: #include "llvm/ADT/StringRef.h"
+// CHECK-NEXT: #include "llvm/Frontend/Directive/Spelling.h"
// CHECK-NEXT: #include "llvm/Support/Compiler.h"
// CHECK-NEXT: #include <cstddef>
// CHECK-NEXT: #include <utility>
@@ -54,8 +55,6 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-NEXT: namespace llvm {
// CHECK-NEXT: namespace tdl {
// CHECK-EMPTY:
-// CHECK-NEXT: struct VersionRange { int Min = 1; int Max = 0x7fffffff; };
-// CHECK-EMPTY:
// CHECK-NEXT: enum class Association {
// CHECK-NEXT: Block,
// CHECK-NEXT: Declaration,
@@ -102,14 +101,14 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-NEXT: static constexpr std::size_t Clause_enumSize = 4;
// CHECK-EMPTY:
// CHECK-NEXT: // Enumeration helper functions
-// CHECK-NEXT: LLVM_ABI std::pair<Directive, VersionRange> getTdlDirectiveKindAndVersions(StringRef Str);
+// CHECK-NEXT: LLVM_ABI std::pair<Directive, directive::VersionRange> getTdlDirectiveKindAndVersions(StringRef Str);
// CHECK-NEXT: inline Directive getTdlDirectiveKind(StringRef Str) {
// CHECK-NEXT: return getTdlDirectiveKindAndVersions(Str).first;
// CHECK-NEXT: }
// CHECK-EMPTY:
// CHECK-NEXT: LLVM_ABI StringRef getTdlDirectiveName(Directive D, unsigned Ver = 0);
// CHECK-EMPTY:
-// CHECK-NEXT: LLVM_ABI std::pair<Clause, VersionRange> getTdlClauseKindAndVersions(StringRef Str);
+// CHECK-NEXT: LLVM_ABI std::pair<Clause, directive::VersionRange> getTdlClauseKindAndVersions(StringRef Str);
// CHECK-EMPTY:
// CHECK-NEXT: inline Clause getTdlClauseKind(StringRef Str) {
// CHECK-NEXT: return getTdlClauseKindAndVersions(Str).first;
@@ -267,17 +266,18 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// IMPL: #ifdef GEN_DIRECTIVES_IMPL
// IMPL-NEXT: #undef GEN_DIRECTIVES_IMPL
// IMPL-EMPTY:
+// IMPL-NEXT: #include "llvm/Frontend/Directive/Spelling.h"
// IMPL-NEXT: #include "llvm/Support/ErrorHandling.h"
// IMPL-NEXT: #include <utility>
// IMPL-EMPTY:
-// IMPL-NEXT: std::pair<llvm::tdl::Directive, llvm::tdl::VersionRange> llvm::tdl::getTdlDirectiveKindAndVersions(llvm::StringRef Str) {
-// IMPL-NEXT: VersionRange All{}; // Default-initialized to "all-versions"
-// IMPL-NEXT: return StringSwitch<std::pair<Directive, VersionRange>>(Str)
+// IMPL-NEXT: std::pair<llvm::tdl::Directive, llvm::directive::VersionRange> llvm::tdl::getTdlDirectiveKindAndVersions(llvm::StringRef Str) {
+// IMPL-NEXT: directive::VersionRange All; // Default-initialized to "all versions"
+// IMPL-NEXT: return StringSwitch<std::pair<Directive, directive::VersionRange>>(Str)
// IMPL-NEXT: .Case("dira", {TDLD_dira, All})
// IMPL-NEXT: .Default({TDLD_dira, All});
// IMPL-NEXT: }
// IMPL-EMPTY:
-// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlDirectiveName(llvm::tdl::Directive Kind, unsigned) {
+// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlDirectiveName(llvm::tdl::Directive Kind, unsigned Version) {
// IMPL-NEXT: switch (Kind) {
// IMPL-NEXT: case TDLD_dira:
// IMPL-NEXT: return "dira";
@@ -285,9 +285,9 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// IMPL-NEXT: llvm_unreachable("Invalid Tdl Directive kind");
// IMPL-NEXT: }
// IMPL-EMPTY:
-// IMPL-NEXT: std::pair<llvm::tdl::Clause, llvm::tdl::VersionRange> llvm::tdl::getTdlClauseKindAndVersions(llvm::StringRef Str) {
-// IMPL-NEXT: VersionRange All{}; // Default-initialized to "all-versions"
-// IMPL-NEXT: return StringSwitch<std::pair<Clause, VersionRange>>(Str)
+// IMPL-NEXT: std::pair<llvm::tdl::Clause, llvm::directive::VersionRange> llvm::tdl::getTdlClauseKindAndVersions(llvm::StringRef Str) {
+// IMPL-NEXT: directive::VersionRange All; // Default-initialized to "all versions"
+// IMPL-NEXT: return StringSwitch<std::pair<Clause, directive::VersionRange>>(Str)
// IMPL-NEXT: .Case("clausea", {TDLC_clauseb, All})
// IMPL-NEXT: .Case("clauseb", {TDLC_clauseb, All})
// IMPL-NEXT: .Case("clausec", {TDLC_clausec, All})
@@ -295,7 +295,7 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// IMPL-NEXT: .Default({TDLC_clauseb, All});
// IMPL-NEXT: }
// IMPL-EMPTY:
-// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlClauseName(llvm::tdl::Clause Kind, unsigned) {
+// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlClauseName(llvm::tdl::Clause Kind, unsigned Version) {
// IMPL-NEXT: switch (Kind) {
// IMPL-NEXT: case TDLC_clausea:
// IMPL-NEXT: return "clausea";
diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
index 75f796abb7ce6..84438de067dce 100644
--- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
@@ -77,6 +77,19 @@ static std::string getIdentifierName(const Record *Rec, StringRef Prefix) {
return Prefix.str() + BaseRecord(Rec).getFormattedName();
}
+using RecordWithSpelling = std::pair<const Record *, Spelling::Value>;
+
+static std::vector<RecordWithSpelling>
+getSpellings(ArrayRef<const Record *> Records) {
+ std::vector<RecordWithSpelling> List;
+ for (const Record *R : Records) {
+ Clause C(R);
+ llvm::transform(C.getSpellings(), std::back_inserter(List),
+ [R](Spelling::Value V) { return std::make_pair(R, V); });
+ }
+ return List;
+}
+
static void generateEnumExports(ArrayRef<const Record *> Records,
raw_ostream &OS, StringRef Enum,
StringRef Prefix) {
@@ -270,6 +283,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << "#include \"llvm/ADT/BitmaskEnum.h\"\n";
OS << "#include \"llvm/ADT/StringRef.h\"\n";
+ OS << "#include \"llvm/Frontend/Directive/Spelling.h\"\n";
OS << "#include \"llvm/Support/Compiler.h\"\n";
OS << "#include <cstddef>\n"; // for size_t
OS << "#include <utility>\n"; // for std::pair
@@ -285,13 +299,6 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
if (DirLang.hasEnableBitmaskEnumInNamespace())
OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n";
-#define AS_STRING_HELPER_TO_GET_THE_ARGUMENT_MACRO_EXPANDED(x) #x
-#define AS_STRING(x) AS_STRING_HELPER_TO_GET_THE_ARGUMENT_MACRO_EXPANDED(x)
- OS << "\n";
- OS << AS_STRING(STRUCT_VERSION_RANGE) << ";\n";
-#undef AS_STRING
-#undef AS_STRING_HELPER_TO_GET_THE_ARGUMENT_MACRO_EXPANDED
-
// Emit Directive associations
std::vector<const Record *> Associations;
copy_if(DirLang.getAssociations(), std::back_inserter(Associations),
@@ -324,7 +331,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << "\n";
OS << "// Enumeration helper functions\n";
- OS << "LLVM_ABI std::pair<Directive, VersionRange> get" << Lang
+ OS << "LLVM_ABI std::pair<Directive, directive::VersionRange> get" << Lang
<< "DirectiveKindAndVersions(StringRef Str);\n";
OS << "inline Directive get" << Lang << "DirectiveKind(StringRef Str) {\n";
@@ -336,7 +343,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
<< "DirectiveName(Directive D, unsigned Ver = 0);\n";
OS << "\n";
- OS << "LLVM_ABI std::pair<Clause, VersionRange> get" << Lang
+ OS << "LLVM_ABI std::pair<Clause, directive::VersionRange> get" << Lang
<< "ClauseKindAndVersions(StringRef Str);\n";
OS << "\n";
@@ -373,6 +380,33 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << "#endif // LLVM_" << Lang << "_INC\n";
}
+// Given a list of spellings (for a given clause/directive), order them
+// in a way that allows the use of binary search to locate a spelling
+// for a specified version.
+static std::vector<Spelling::Value>
+orderSpellings(ArrayRef<Spelling::Value> Spellings) {
+ std::vector<Spelling::Value> List(Spellings.begin(), Spellings.end());
+
+ // There are two intertwined orderings: (1) the order between spellings
+ // (used here), and (2) the order between a spelling and a version (used
+ // at runtime).
+ // Define order (2) as such that the first A that is not less than V
+ // will be the selected spelling given V. Specifically,
+ // V <(2) A <=> V < A.Min
+ // A <(2) V <=> A.Max < V
+ //
+ // The orders have to be comp...
[truncated]
|
@llvm/pr-subscribers-tablegen Author: Krzysztof Parzyszek (kparzysz) ChangesIn "get<lang>DirectiveName(Kind, Version)", return the spelling that corresponds to Version, and in "get<lang>DirectiveKindAndVersions(Name)" return the pair {Kind, VersionRange}, where VersionRange contains the minimum and the maximum versions that allow "Name" as a spelling. This applies to clauses as well. In general it applies to classes that have spellings (defined via TableGen class "Spelling"). Given a Kind and a Version, getting the corresponding spelling requires a runtime search (which can fail in a general case). To avoid generating the search function inline, a small additional component of llvm/Frontent was added: LLVMFrontendDirective. The corresponding header file also defines C++ classes "Spelling" and "VersionRange", which are used in TableGen/DirectiveEmitter as well. For background information see Patch is 26.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143021.diff 10 Files Affected:
diff --git a/llvm/include/llvm/Frontend/Directive/Spelling.h b/llvm/include/llvm/Frontend/Directive/Spelling.h
new file mode 100644
index 0000000000000..3ba0ae2296535
--- /dev/null
+++ b/llvm/include/llvm/Frontend/Directive/Spelling.h
@@ -0,0 +1,39 @@
+//===-- Spelling.h ------------------------------------------------ C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_FRONTEND_DIRECTIVE_SPELLING_H
+#define LLVM_FRONTEND_DIRECTIVE_SPELLING_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+
+#include <limits>
+
+namespace llvm::directive {
+
+struct VersionRange {
+ static constexpr int MaxValue = std::numeric_limits<int>::max();
+ int Min = 1;
+ int Max = MaxValue;
+};
+
+inline bool operator<(const VersionRange &A, const VersionRange &B) {
+ if (A.Min != B.Min)
+ return A.Min < B.Min;
+ return A.Max < B.Max;
+}
+
+struct Spelling {
+ StringRef Name;
+ VersionRange Versions;
+};
+
+StringRef FindName(llvm::iterator_range<const Spelling *>, unsigned Version);
+
+} // namespace llvm::directive
+
+#endif // LLVM_FRONTEND_DIRECTIVE_SPELLING_H
diff --git a/llvm/include/llvm/TableGen/DirectiveEmitter.h b/llvm/include/llvm/TableGen/DirectiveEmitter.h
index dc2f75083ec0d..a2256716a7c8b 100644
--- a/llvm/include/llvm/TableGen/DirectiveEmitter.h
+++ b/llvm/include/llvm/TableGen/DirectiveEmitter.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Frontend/Directive/Spelling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/TableGen/Record.h"
#include <algorithm>
@@ -113,29 +114,19 @@ class Versioned {
constexpr static int IntWidth = 8 * sizeof(int);
};
-// Range of specification versions: [Min, Max]
-// Default value: all possible versions.
-// This is the same structure as the one emitted into the generated sources.
-#define STRUCT_VERSION_RANGE \
- struct VersionRange { \
- int Min = 1; \
- int Max = 0x7fffffff; \
- }
-
-STRUCT_VERSION_RANGE;
-
class Spelling : public Versioned {
public:
- using Value = std::pair<StringRef, VersionRange>;
+ using Value = llvm::directive::Spelling;
Spelling(const Record *Def) : Def(Def) {}
StringRef getText() const { return Def->getValueAsString("spelling"); }
- VersionRange getVersions() const {
- return VersionRange{getMinVersion(Def), getMaxVersion(Def)};
+ llvm::directive::VersionRange getVersions() const {
+ return llvm::directive::VersionRange{getMinVersion(Def),
+ getMaxVersion(Def)};
}
- Value get() const { return std::make_pair(getText(), getVersions()); }
+ Value get() const { return Value{getText(), getVersions()}; }
private:
const Record *Def;
@@ -177,9 +168,9 @@ class BaseRecord {
// are added.
Spelling::Value Oldest{"not found", {/*Min=*/INT_MAX, 0}};
for (auto V : getSpellings())
- if (V.second.Min < Oldest.second.Min)
+ if (V.Versions.Min < Oldest.Versions.Min)
Oldest = V;
- return Oldest.first;
+ return Oldest.Name;
}
// Returns the name of the directive formatted for output. Whitespace are
diff --git a/llvm/lib/Frontend/CMakeLists.txt b/llvm/lib/Frontend/CMakeLists.txt
index b305ce7d771ce..3b31e6f8dec96 100644
--- a/llvm/lib/Frontend/CMakeLists.txt
+++ b/llvm/lib/Frontend/CMakeLists.txt
@@ -1,4 +1,5 @@
add_subdirectory(Atomic)
+add_subdirectory(Directive)
add_subdirectory(Driver)
add_subdirectory(HLSL)
add_subdirectory(OpenACC)
diff --git a/llvm/lib/Frontend/Directive/CMakeLists.txt b/llvm/lib/Frontend/Directive/CMakeLists.txt
new file mode 100644
index 0000000000000..a567e1affb171
--- /dev/null
+++ b/llvm/lib/Frontend/Directive/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_llvm_component_library(LLVMFrontendDirective
+ Spelling.cpp
+
+ LINK_COMPONENTS
+ Support
+)
diff --git a/llvm/lib/Frontend/Directive/Spelling.cpp b/llvm/lib/Frontend/Directive/Spelling.cpp
new file mode 100644
index 0000000000000..c808e625ee4fd
--- /dev/null
+++ b/llvm/lib/Frontend/Directive/Spelling.cpp
@@ -0,0 +1,31 @@
+//===-- Spelling.cpp ---------------------------------------------- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Frontend/Directive/Spelling.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MathExtras.h"
+
+#include <cassert>
+
+llvm::StringRef llvm::directive::FindName(
+ llvm::iterator_range<const llvm::directive::Spelling *> Range,
+ unsigned Version) {
+ assert(llvm::isInt<8 * sizeof(int)>(Version) && "Version value out of range");
+
+ int V = Version;
+ Spelling Tmp{StringRef(), {V, V}};
+ auto F =
+ llvm::lower_bound(Range, Tmp, [](const Spelling &A, const Spelling &B) {
+ return A.Versions < B.Versions;
+ });
+ if (F != Range.end())
+ return F->Name;
+ return StringRef();
+}
diff --git a/llvm/lib/Frontend/OpenACC/CMakeLists.txt b/llvm/lib/Frontend/OpenACC/CMakeLists.txt
index f352014978690..4664b71407c48 100644
--- a/llvm/lib/Frontend/OpenACC/CMakeLists.txt
+++ b/llvm/lib/Frontend/OpenACC/CMakeLists.txt
@@ -9,5 +9,5 @@ add_llvm_component_library(LLVMFrontendOpenACC
acc_gen
)
-target_link_libraries(LLVMFrontendOpenACC LLVMSupport)
+target_link_libraries(LLVMFrontendOpenACC LLVMSupport LLVMFrontendDirective)
diff --git a/llvm/lib/Frontend/OpenMP/CMakeLists.txt b/llvm/lib/Frontend/OpenMP/CMakeLists.txt
index 35c607866a94e..5bf15ca3a8991 100644
--- a/llvm/lib/Frontend/OpenMP/CMakeLists.txt
+++ b/llvm/lib/Frontend/OpenMP/CMakeLists.txt
@@ -23,4 +23,5 @@ add_llvm_component_library(LLVMFrontendOpenMP
BitReader
FrontendOffloading
FrontendAtomic
+ FrontendDirective
)
diff --git a/llvm/test/TableGen/directive1.td b/llvm/test/TableGen/directive1.td
index 8196a30d03df4..1c8da26f50f4b 100644
--- a/llvm/test/TableGen/directive1.td
+++ b/llvm/test/TableGen/directive1.td
@@ -54,6 +54,7 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-NEXT: #include "llvm/ADT/ArrayRef.h"
// CHECK-NEXT: #include "llvm/ADT/BitmaskEnum.h"
// CHECK-NEXT: #include "llvm/ADT/StringRef.h"
+// CHECK-NEXT: #include "llvm/Frontend/Directive/Spelling.h"
// CHECK-NEXT: #include "llvm/Support/Compiler.h"
// CHECK-NEXT: #include <cstddef>
// CHECK-NEXT: #include <utility>
@@ -63,8 +64,6 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-EMPTY:
// CHECK-NEXT: LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
// CHECK-EMPTY:
-// CHECK-NEXT: struct VersionRange { int Min = 1; int Max = 0x7fffffff; };
-// CHECK-EMPTY:
// CHECK-NEXT: enum class Association {
// CHECK-NEXT: Block,
// CHECK-NEXT: Declaration,
@@ -126,14 +125,14 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-NEXT: constexpr auto TDLCV_valc = AKind::TDLCV_valc;
// CHECK-EMPTY:
// CHECK-NEXT: // Enumeration helper functions
-// CHECK-NEXT: LLVM_ABI std::pair<Directive, VersionRange> getTdlDirectiveKindAndVersions(StringRef Str);
+// CHECK-NEXT: LLVM_ABI std::pair<Directive, directive::VersionRange> getTdlDirectiveKindAndVersions(StringRef Str);
// CHECK-NEXT: inline Directive getTdlDirectiveKind(StringRef Str) {
// CHECK-NEXT: return getTdlDirectiveKindAndVersions(Str).first;
// CHECK-NEXT: }
// CHECK-EMPTY:
// CHECK-NEXT: LLVM_ABI StringRef getTdlDirectiveName(Directive D, unsigned Ver = 0);
// CHECK-EMPTY:
-// CHECK-NEXT: LLVM_ABI std::pair<Clause, VersionRange> getTdlClauseKindAndVersions(StringRef Str);
+// CHECK-NEXT: LLVM_ABI std::pair<Clause, directive::VersionRange> getTdlClauseKindAndVersions(StringRef Str);
// CHECK-EMPTY:
// CHECK-NEXT: inline Clause getTdlClauseKind(StringRef Str) {
// CHECK-NEXT: return getTdlClauseKindAndVersions(Str).first;
@@ -320,17 +319,18 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// IMPL: #ifdef GEN_DIRECTIVES_IMPL
// IMPL-NEXT: #undef GEN_DIRECTIVES_IMPL
// IMPL-EMPTY:
+// IMPL-NEXT: #include "llvm/Frontend/Directive/Spelling.h"
// IMPL-NEXT: #include "llvm/Support/ErrorHandling.h"
// IMPL-NEXT: #include <utility>
// IMPL-EMPTY:
-// IMPL-NEXT: std::pair<llvm::tdl::Directive, llvm::tdl::VersionRange> llvm::tdl::getTdlDirectiveKindAndVersions(llvm::StringRef Str) {
-// IMPL-NEXT: VersionRange All{}; // Default-initialized to "all-versions"
-// IMPL-NEXT: return StringSwitch<std::pair<Directive, VersionRange>>(Str)
+// IMPL-NEXT: std::pair<llvm::tdl::Directive, llvm::directive::VersionRange> llvm::tdl::getTdlDirectiveKindAndVersions(llvm::StringRef Str) {
+// IMPL-NEXT: directive::VersionRange All; // Default-initialized to "all versions"
+// IMPL-NEXT: return StringSwitch<std::pair<Directive, directive::VersionRange>>(Str)
// IMPL-NEXT: .Case("dira", {TDLD_dira, All})
// IMPL-NEXT: .Default({TDLD_dira, All});
// IMPL-NEXT: }
// IMPL-EMPTY:
-// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlDirectiveName(llvm::tdl::Directive Kind, unsigned) {
+// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlDirectiveName(llvm::tdl::Directive Kind, unsigned Version) {
// IMPL-NEXT: switch (Kind) {
// IMPL-NEXT: case TDLD_dira:
// IMPL-NEXT: return "dira";
@@ -338,23 +338,29 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// IMPL-NEXT: llvm_unreachable("Invalid Tdl Directive kind");
// IMPL-NEXT: }
// IMPL-EMPTY:
-// IMPL-NEXT: std::pair<llvm::tdl::Clause, llvm::tdl::VersionRange> llvm::tdl::getTdlClauseKindAndVersions(llvm::StringRef Str) {
-// IMPL-NEXT: VersionRange All{}; // Default-initialized to "all-versions"
-// IMPL-NEXT: return StringSwitch<std::pair<Clause, VersionRange>>(Str)
+// IMPL-NEXT: std::pair<llvm::tdl::Clause, llvm::directive::VersionRange> llvm::tdl::getTdlClauseKindAndVersions(llvm::StringRef Str) {
+// IMPL-NEXT: directive::VersionRange All; // Default-initialized to "all versions"
+// IMPL-NEXT: return StringSwitch<std::pair<Clause, directive::VersionRange>>(Str)
// IMPL-NEXT: .Case("clausea", {TDLC_clausea, All})
// IMPL-NEXT: .Case("clauseb", {TDLC_clauseb, All})
// IMPL-NEXT: .Case("clausec", {TDLC_clausec, All})
+// IMPL-NEXT: .Case("ccccccc", {TDLC_clausec, All})
// IMPL-NEXT: .Default({TDLC_clauseb, All});
// IMPL-NEXT: }
// IMPL-EMPTY:
-// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlClauseName(llvm::tdl::Clause Kind, unsigned) {
+// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlClauseName(llvm::tdl::Clause Kind, unsigned Version) {
// IMPL-NEXT: switch (Kind) {
// IMPL-NEXT: case TDLC_clausea:
// IMPL-NEXT: return "clausea";
// IMPL-NEXT: case TDLC_clauseb:
// IMPL-NEXT: return "clauseb";
-// IMPL-NEXT: case TDLC_clausec:
-// IMPL-NEXT: return "clausec";
+// IMPL-NEXT: case TDLC_clausec: {
+// IMPL-NEXT: static const llvm::directive::Spelling TDLC_clausec_spellings[] = {
+// IMPL-NEXT: {"clausec", {1, 2147483647}},
+// IMPL-NEXT: {"ccccccc", {1, 2147483647}},
+// IMPL-NEXT: };
+// IMPL-NEXT: return llvm::directive::FindName(TDLC_clausec_spellings, Version);
+// IMPL-NEXT: }
// IMPL-NEXT: }
// IMPL-NEXT: llvm_unreachable("Invalid Tdl Clause kind");
// IMPL-NEXT: }
diff --git a/llvm/test/TableGen/directive2.td b/llvm/test/TableGen/directive2.td
index ead6aa2637b76..3a64bb3900a31 100644
--- a/llvm/test/TableGen/directive2.td
+++ b/llvm/test/TableGen/directive2.td
@@ -47,6 +47,7 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-EMPTY:
// CHECK-NEXT: #include "llvm/ADT/ArrayRef.h"
// CHECK-NEXT: #include "llvm/ADT/StringRef.h"
+// CHECK-NEXT: #include "llvm/Frontend/Directive/Spelling.h"
// CHECK-NEXT: #include "llvm/Support/Compiler.h"
// CHECK-NEXT: #include <cstddef>
// CHECK-NEXT: #include <utility>
@@ -54,8 +55,6 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-NEXT: namespace llvm {
// CHECK-NEXT: namespace tdl {
// CHECK-EMPTY:
-// CHECK-NEXT: struct VersionRange { int Min = 1; int Max = 0x7fffffff; };
-// CHECK-EMPTY:
// CHECK-NEXT: enum class Association {
// CHECK-NEXT: Block,
// CHECK-NEXT: Declaration,
@@ -102,14 +101,14 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// CHECK-NEXT: static constexpr std::size_t Clause_enumSize = 4;
// CHECK-EMPTY:
// CHECK-NEXT: // Enumeration helper functions
-// CHECK-NEXT: LLVM_ABI std::pair<Directive, VersionRange> getTdlDirectiveKindAndVersions(StringRef Str);
+// CHECK-NEXT: LLVM_ABI std::pair<Directive, directive::VersionRange> getTdlDirectiveKindAndVersions(StringRef Str);
// CHECK-NEXT: inline Directive getTdlDirectiveKind(StringRef Str) {
// CHECK-NEXT: return getTdlDirectiveKindAndVersions(Str).first;
// CHECK-NEXT: }
// CHECK-EMPTY:
// CHECK-NEXT: LLVM_ABI StringRef getTdlDirectiveName(Directive D, unsigned Ver = 0);
// CHECK-EMPTY:
-// CHECK-NEXT: LLVM_ABI std::pair<Clause, VersionRange> getTdlClauseKindAndVersions(StringRef Str);
+// CHECK-NEXT: LLVM_ABI std::pair<Clause, directive::VersionRange> getTdlClauseKindAndVersions(StringRef Str);
// CHECK-EMPTY:
// CHECK-NEXT: inline Clause getTdlClauseKind(StringRef Str) {
// CHECK-NEXT: return getTdlClauseKindAndVersions(Str).first;
@@ -267,17 +266,18 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// IMPL: #ifdef GEN_DIRECTIVES_IMPL
// IMPL-NEXT: #undef GEN_DIRECTIVES_IMPL
// IMPL-EMPTY:
+// IMPL-NEXT: #include "llvm/Frontend/Directive/Spelling.h"
// IMPL-NEXT: #include "llvm/Support/ErrorHandling.h"
// IMPL-NEXT: #include <utility>
// IMPL-EMPTY:
-// IMPL-NEXT: std::pair<llvm::tdl::Directive, llvm::tdl::VersionRange> llvm::tdl::getTdlDirectiveKindAndVersions(llvm::StringRef Str) {
-// IMPL-NEXT: VersionRange All{}; // Default-initialized to "all-versions"
-// IMPL-NEXT: return StringSwitch<std::pair<Directive, VersionRange>>(Str)
+// IMPL-NEXT: std::pair<llvm::tdl::Directive, llvm::directive::VersionRange> llvm::tdl::getTdlDirectiveKindAndVersions(llvm::StringRef Str) {
+// IMPL-NEXT: directive::VersionRange All; // Default-initialized to "all versions"
+// IMPL-NEXT: return StringSwitch<std::pair<Directive, directive::VersionRange>>(Str)
// IMPL-NEXT: .Case("dira", {TDLD_dira, All})
// IMPL-NEXT: .Default({TDLD_dira, All});
// IMPL-NEXT: }
// IMPL-EMPTY:
-// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlDirectiveName(llvm::tdl::Directive Kind, unsigned) {
+// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlDirectiveName(llvm::tdl::Directive Kind, unsigned Version) {
// IMPL-NEXT: switch (Kind) {
// IMPL-NEXT: case TDLD_dira:
// IMPL-NEXT: return "dira";
@@ -285,9 +285,9 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// IMPL-NEXT: llvm_unreachable("Invalid Tdl Directive kind");
// IMPL-NEXT: }
// IMPL-EMPTY:
-// IMPL-NEXT: std::pair<llvm::tdl::Clause, llvm::tdl::VersionRange> llvm::tdl::getTdlClauseKindAndVersions(llvm::StringRef Str) {
-// IMPL-NEXT: VersionRange All{}; // Default-initialized to "all-versions"
-// IMPL-NEXT: return StringSwitch<std::pair<Clause, VersionRange>>(Str)
+// IMPL-NEXT: std::pair<llvm::tdl::Clause, llvm::directive::VersionRange> llvm::tdl::getTdlClauseKindAndVersions(llvm::StringRef Str) {
+// IMPL-NEXT: directive::VersionRange All; // Default-initialized to "all versions"
+// IMPL-NEXT: return StringSwitch<std::pair<Clause, directive::VersionRange>>(Str)
// IMPL-NEXT: .Case("clausea", {TDLC_clauseb, All})
// IMPL-NEXT: .Case("clauseb", {TDLC_clauseb, All})
// IMPL-NEXT: .Case("clausec", {TDLC_clausec, All})
@@ -295,7 +295,7 @@ def TDL_DirA : Directive<[Spelling<"dira">]> {
// IMPL-NEXT: .Default({TDLC_clauseb, All});
// IMPL-NEXT: }
// IMPL-EMPTY:
-// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlClauseName(llvm::tdl::Clause Kind, unsigned) {
+// IMPL-NEXT: llvm::StringRef llvm::tdl::getTdlClauseName(llvm::tdl::Clause Kind, unsigned Version) {
// IMPL-NEXT: switch (Kind) {
// IMPL-NEXT: case TDLC_clausea:
// IMPL-NEXT: return "clausea";
diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
index 75f796abb7ce6..84438de067dce 100644
--- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
@@ -77,6 +77,19 @@ static std::string getIdentifierName(const Record *Rec, StringRef Prefix) {
return Prefix.str() + BaseRecord(Rec).getFormattedName();
}
+using RecordWithSpelling = std::pair<const Record *, Spelling::Value>;
+
+static std::vector<RecordWithSpelling>
+getSpellings(ArrayRef<const Record *> Records) {
+ std::vector<RecordWithSpelling> List;
+ for (const Record *R : Records) {
+ Clause C(R);
+ llvm::transform(C.getSpellings(), std::back_inserter(List),
+ [R](Spelling::Value V) { return std::make_pair(R, V); });
+ }
+ return List;
+}
+
static void generateEnumExports(ArrayRef<const Record *> Records,
raw_ostream &OS, StringRef Enum,
StringRef Prefix) {
@@ -270,6 +283,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << "#include \"llvm/ADT/BitmaskEnum.h\"\n";
OS << "#include \"llvm/ADT/StringRef.h\"\n";
+ OS << "#include \"llvm/Frontend/Directive/Spelling.h\"\n";
OS << "#include \"llvm/Support/Compiler.h\"\n";
OS << "#include <cstddef>\n"; // for size_t
OS << "#include <utility>\n"; // for std::pair
@@ -285,13 +299,6 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
if (DirLang.hasEnableBitmaskEnumInNamespace())
OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n";
-#define AS_STRING_HELPER_TO_GET_THE_ARGUMENT_MACRO_EXPANDED(x) #x
-#define AS_STRING(x) AS_STRING_HELPER_TO_GET_THE_ARGUMENT_MACRO_EXPANDED(x)
- OS << "\n";
- OS << AS_STRING(STRUCT_VERSION_RANGE) << ";\n";
-#undef AS_STRING
-#undef AS_STRING_HELPER_TO_GET_THE_ARGUMENT_MACRO_EXPANDED
-
// Emit Directive associations
std::vector<const Record *> Associations;
copy_if(DirLang.getAssociations(), std::back_inserter(Associations),
@@ -324,7 +331,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << "\n";
OS << "// Enumeration helper functions\n";
- OS << "LLVM_ABI std::pair<Directive, VersionRange> get" << Lang
+ OS << "LLVM_ABI std::pair<Directive, directive::VersionRange> get" << Lang
<< "DirectiveKindAndVersions(StringRef Str);\n";
OS << "inline Directive get" << Lang << "DirectiveKind(StringRef Str) {\n";
@@ -336,7 +343,7 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
<< "DirectiveName(Directive D, unsigned Ver = 0);\n";
OS << "\n";
- OS << "LLVM_ABI std::pair<Clause, VersionRange> get" << Lang
+ OS << "LLVM_ABI std::pair<Clause, directive::VersionRange> get" << Lang
<< "ClauseKindAndVersions(StringRef Str);\n";
OS << "\n";
@@ -373,6 +380,33 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
OS << "#endif // LLVM_" << Lang << "_INC\n";
}
+// Given a list of spellings (for a given clause/directive), order them
+// in a way that allows the use of binary search to locate a spelling
+// for a specified version.
+static std::vector<Spelling::Value>
+orderSpellings(ArrayRef<Spelling::Value> Spellings) {
+ std::vector<Spelling::Value> List(Spellings.begin(), Spellings.end());
+
+ // There are two intertwined orderings: (1) the order between spellings
+ // (used here), and (2) the order between a spelling and a version (used
+ // at runtime).
+ // Define order (2) as such that the first A that is not less than V
+ // will be the selected spelling given V. Specifically,
+ // V <(2) A <=> V < A.Min
+ // A <(2) V <=> A.Max < V
+ //
+ // The orders have to be comp...
[truncated]
|
LGTM, just some minor comments. |
The default value of the Version parameter in get<Lang><Enum>Name() was 0, which was not in the range [1, 0x7fffffff]. To fix this, it was either to change the default value to 1, or to lower the minimum version to 0. The latter seemed like a better choice, since 0 is a natural choice for a lower bound on version numbers.
Running local checks before pushing updates... |
✅ With the latest revision this PR passed the C/C++ code formatter. |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/23/builds/11030 Here is the relevant piece of the build log for the reference
|
…#143021) In "get<lang>DirectiveName(Kind, Version)", return the spelling that corresponds to Version, and in "get<lang>DirectiveKindAndVersions(Name)" return the pair {Kind, VersionRange}, where VersionRange contains the minimum and the maximum versions that allow "Name" as a spelling. This applies to clauses as well. In general it applies to classes that have spellings (defined via TableGen class "Spelling"). Given a Kind and a Version, getting the corresponding spelling requires a runtime search (which can fail in a general case). To avoid generating the search function inline, a small additional component of llvm/Frontent was added: LLVMFrontendDirective. The corresponding header file also defines C++ classes "Spelling" and "VersionRange", which are used in TableGen/DirectiveEmitter as well. For background information see https://discourse.llvm.org/t/rfc-alternative-spellings-of-openmp-directives/85507
…#143021) In "get<lang>DirectiveName(Kind, Version)", return the spelling that corresponds to Version, and in "get<lang>DirectiveKindAndVersions(Name)" return the pair {Kind, VersionRange}, where VersionRange contains the minimum and the maximum versions that allow "Name" as a spelling. This applies to clauses as well. In general it applies to classes that have spellings (defined via TableGen class "Spelling"). Given a Kind and a Version, getting the corresponding spelling requires a runtime search (which can fail in a general case). To avoid generating the search function inline, a small additional component of llvm/Frontent was added: LLVMFrontendDirective. The corresponding header file also defines C++ classes "Spelling" and "VersionRange", which are used in TableGen/DirectiveEmitter as well. For background information see https://discourse.llvm.org/t/rfc-alternative-spellings-of-openmp-directives/85507
…#143021) In "get<lang>DirectiveName(Kind, Version)", return the spelling that corresponds to Version, and in "get<lang>DirectiveKindAndVersions(Name)" return the pair {Kind, VersionRange}, where VersionRange contains the minimum and the maximum versions that allow "Name" as a spelling. This applies to clauses as well. In general it applies to classes that have spellings (defined via TableGen class "Spelling"). Given a Kind and a Version, getting the corresponding spelling requires a runtime search (which can fail in a general case). To avoid generating the search function inline, a small additional component of llvm/Frontent was added: LLVMFrontendDirective. The corresponding header file also defines C++ classes "Spelling" and "VersionRange", which are used in TableGen/DirectiveEmitter as well. For background information see https://discourse.llvm.org/t/rfc-alternative-spellings-of-openmp-directives/85507
In "getDirectiveName(Kind, Version)", return the spelling that corresponds to Version, and in "getDirectiveKindAndVersions(Name)" return the pair {Kind, VersionRange}, where VersionRange contains the minimum and the maximum versions that allow "Name" as a spelling. This applies to clauses as well. In general it applies to classes that have spellings (defined via TableGen class "Spelling").
Given a Kind and a Version, getting the corresponding spelling requires a runtime search (which can fail in a general case). To avoid generating the search function inline, a small additional component of llvm/Frontent was added: LLVMFrontendDirective. The corresponding header file also defines C++ classes "Spelling" and "VersionRange", which are used in TableGen/DirectiveEmitter as well.
For background information see
https://discourse.llvm.org/t/rfc-alternative-spellings-of-openmp-directives/85507