================
@@ -0,0 +1,195 @@
+#include "TableGenBackends.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Record.h"
+
+using namespace llvm;
+
+namespace {
+
+StringRef recordKindToMacro(const Record *R) {
+  if (R->isSubClassOf("UnaryTrait"))
+    return "TYPE_TRAIT_1";
+  if (R->isSubClassOf("BinaryTrait"))
+    return "TYPE_TRAIT_2";
+  if (R->isSubClassOf("VariadicTrait"))
+    return "TYPE_TRAIT_N";
+  if (R->isSubClassOf("ArrayTrait"))
+    return "ARRAY_TYPE_TRAIT";
+  if (R->isSubClassOf("ExpressionTrait"))
+    return "EXPRESSION_TRAIT";
+  if (R->isSubClassOf("UnaryExprOrTypeTrait"))
+    return "UNARY_EXPR_OR_TYPE_TRAIT";
+  if (R->isSubClassOf("CXX11UnaryExprOrTypeTrait"))
+    return "CXX11_UNARY_EXPR_OR_TYPE_TRAIT";
+  if (R->isSubClassOf("TransformTypeTrait"))
+    return "TRANSFORM_TYPE_TRAIT_DEF";
+
+  llvm_unreachable("unexpected Trait subclass");
+}
+
+void emitMacro(const Record *R, raw_ostream &OS) {
+  OS << recordKindToMacro(R) << "(";
+  if (R->isSubClassOf("TransformTypeTrait")) {
+    const StringRef StdName = R->getValueAsString("StdName");
+    OS << R->getName() << ", " << StdName;
+  } else {
+    OS << R->getValueAsString("Spelling") << ", " << R->getName() << ", "
+       << R->getValueAsString("KeyFlag");
+  }
+  OS << ")\n";
+}
+
+void emitMacroDefs(const RecordKeeper &Records, raw_ostream &OS) {
+  constexpr std::pair<StringRef, StringRef> MacroDefs[] = {
+      {"TYPE_TRAIT_1", "(I,E,K)"},
+      {"TYPE_TRAIT_2", "(I,E,K)"},
+      {"TYPE_TRAIT_N", "(I,E,K)"},
+      {"ARRAY_TYPE_TRAIT", "(I,E,K)"},
+      {"UNARY_EXPR_OR_TYPE_TRAIT", "(I,E,K)"},
+      {"CXX11_UNARY_EXPR_OR_TYPE_TRAIT", "(I,E,K)"},
+      {"EXPRESSION_TRAIT", "(I,E,K)"},
+      {"TRANSFORM_TYPE_TRAIT_DEF", "(K, Trait)"},
+  };
+
+  for (const auto &[MacroName, MacroArgs] : MacroDefs) {
+    OS << "#ifndef " << MacroName << "\n"
+       << "#define " << MacroName << MacroArgs << "\n"
+       << "#endif\n";
+  }
+
+  OS << '\n';
+
+  for (const Record *R : Records.getAllDerivedDefinitions("Trait"))
+    emitMacro(R, OS);
+
+  for (const auto &[MacroName, _] : reverse(MacroDefs))
+    OS << "#undef " << MacroName << "\n";
+}
+
+template <typename RangeT>
+void emitEnumerators(raw_ostream &OS, RangeT &&Range) {
+  for (const Record *R : Range)
+    OS << "  " << R->getValueAsString("Prefix") << '_' << R->getName() << 
",\n";
+}
+
+void emitEnums(const RecordKeeper &Records, raw_ostream &OS) {
+  const auto UnaryTraits = Records.getAllDerivedDefinitions("UnaryTrait");
+  const auto BinaryTraits = Records.getAllDerivedDefinitions("BinaryTrait");
+  const auto VariadicTraits = 
Records.getAllDerivedDefinitions("VariadicTrait");
+
+  OS << "/// Names for traits that operate specifically on types.\n"
+        "enum TypeTrait {\n";
+  emitEnumerators(OS, UnaryTraits);
+  OS << "  UTT_Last = " << UnaryTraits.size() - 1
+     << ", // UTT_Last == last UTT_XX in the enum.\n";
+
+  emitEnumerators(OS, BinaryTraits);
+  OS << "  BTT_Last = " << UnaryTraits.size() + BinaryTraits.size() - 1
+     << ", // BTT_Last == last BTT_XX in the enum.\n";
+
+  emitEnumerators(OS, VariadicTraits);
+  OS << "  TT_Last = "
+     << UnaryTraits.size() + BinaryTraits.size() + VariadicTraits.size() - 1
+     << " // TT_Last == last TT_XX in the enum.\n"
+     << "};\n\n";
+
+  const auto ArrayTraits = Records.getAllDerivedDefinitions("ArrayTrait");
+  OS << "/// Names for the array type traits.\n"
+        "enum ArrayTypeTrait {\n";
+  emitEnumerators(OS, ArrayTraits);
+  OS << "  ATT_Last = " << ArrayTraits.size() - 1
+     << " // ATT_Last == last ATT\n"
+     << "};\n\n";
+
+  const auto UETTs = Records.getAllDerivedDefinitions("UnaryExprOrTypeTrait");
+  const auto CXX11UETTs =
+      Records.getAllDerivedDefinitions("CXX11UnaryExprOrTypeTrait");
+  OS << "/// Names for the \"expression or type\" traits.\n"
+        "enum UnaryExprOrTypeTrait {\n";
+  emitEnumerators(OS, concat<const Record *const>(UETTs, CXX11UETTs));
+  OS << "  UETT_Last = " << UETTs.size() + CXX11UETTs.size() - 1
+     << " // UETT_Last == last UETT_XX in the enum.\n"
+     << "};\n\n";
+}
+
+template <typename RangeT>
+void emitNamesAndSpellings(raw_ostream &OS, StringRef Name, RangeT Range) {
+  OS << "static constexpr const char *" << Name << "Names[] = {\n";
+  for (const Record *R : Range) {
+    OS << "  \"" << R->getName() << "\",\n";
+  }
+  OS << "};\n\n";
+
+  OS << "static constexpr const char *" << Name << "Spellings[] = {\n";
+  for (const Record *R : Range) {
+    OS << "  \"" << R->getValueAsString("Spelling") << "\",\n";
+  }
+  OS << "};\n\n";
+}
+
+void emitArrays(const RecordKeeper &Records, raw_ostream &OS) {
+  const auto UnaryTraits = Records.getAllDerivedDefinitions("UnaryTrait");
+  const auto BinaryTraits = Records.getAllDerivedDefinitions("BinaryTrait");
+  const auto VariadicTraits = 
Records.getAllDerivedDefinitions("VariadicTrait");
+
+  emitNamesAndSpellings(
+      OS, "TypeTrait",
+      concat<const Record *const>(UnaryTraits, BinaryTraits, VariadicTraits));
+
+  OS << "static constexpr const unsigned TypeTraitArities[] = {\n";
+  interleaveComma(UnaryTraits, OS, [&](auto) { OS << '1'; });
+  if (!UnaryTraits.empty())
+    OS << ",\n";
+  interleaveComma(BinaryTraits, OS, [&](auto) { OS << '2'; });
+  if (!BinaryTraits.empty())
+    OS << ",\n";
+  interleaveComma(VariadicTraits, OS, [&](auto) { OS << '0'; });
+  OS << "\n};\n\n";
+
+  emitNamesAndSpellings(OS, "ArrayTypeTrait",
+                        Records.getAllDerivedDefinitions("ArrayTrait"));
+  emitNamesAndSpellings(
+      OS, "UnaryExprOrTypeTrait",
+      concat<const Record *const>(
+          Records.getAllDerivedDefinitions("UnaryExprOrTypeTrait"),
+          Records.getAllDerivedDefinitions("CXX11UnaryExprOrTypeTrait")));
+}
+
+void emitStdNameCases(const RecordKeeper &Records, raw_ostream &OS) {
+  for (const Record *R : Records.getAllDerivedDefinitions("TypeTrait")) {
+    const StringRef StdName = R->getValueAsString("StdName");
+    if (StdName.empty())
+      continue;
+
+    OS << "  .Case(\"" << StdName
+       << "\", TypeTrait::" << R->getValueAsString("Prefix") << '_'
+       << R->getName() << ")\n";
+  }
+}
+
+} // namespace
+
+void clang::EmitClangTraits(const RecordKeeper &Records, raw_ostream &OS) {
+  OS << "#if defined(EMIT_ENUMS)\n";
----------------
AaronBallman wrote:

Please have the generated file contain a banner at the top reminding people 
that the code is generated.

https://github.com/llvm/llvm-project/pull/201491
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to