[clang] [Clang] Add BuiltinTemplates.td to generate code for builtin templates (PR #123736)

Nikolas Klauser via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 20 00:12:36 PST 2025


================
@@ -0,0 +1,162 @@
+//=- ClangBuiltinsEmitter.cpp - Generate Clang builtin templates-*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits Clang's builtin templates.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TableGenBackends.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+#include <sstream>
+
+using namespace llvm;
+
+static std::string TemplateNameList;
+static std::string CreateBuiltinTemplateParameterList;
+
+namespace {
+struct ParserState {
+  size_t UniqueCounter = 0;
+  size_t CurrentDepth = 0;
+  bool EmittedSizeTInfo = false;
+};
+
+std::pair<std::string, std::string>
+ParseTemplateParameterList(ParserState &PS,
+                           ArrayRef<const Record *> TemplateArgs) {
+  std::vector<std::string> Params;
+  std::unordered_map<std::string, std::string> TemplateNameToParmName;
+
+  std::ostringstream Code;
+  Code << std::boolalpha;
+
+  size_t Position = 0;
+  for (const Record *Arg : TemplateArgs) {
+    std::string ParmName = "Parm" + std::to_string(PS.UniqueCounter++);
+    if (Arg->isSubClassOf("Template")) {
+      ++PS.CurrentDepth;
+      auto [TemplateCode, TPLName] =
+          ParseTemplateParameterList(PS, Arg->getValueAsListOfDefs("Args"));
+      --PS.CurrentDepth;
+      Code << TemplateCode << " auto *" << ParmName
+           << " = TemplateTemplateParmDecl::Create(C, DC, SourceLocation(), "
+           << PS.CurrentDepth << ", " << Position++
+           << ", /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, "
+           << TPLName << ");\n";
+    } else if (Arg->isSubClassOf("Class")) {
+      Code << " auto *" << ParmName
+           << " = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), "
+              "SourceLocation(), "
+           << PS.CurrentDepth << ", " << Position++
+           << ", /*Id=*/nullptr, /*Typename=*/false, "
+           << Arg->getValueAsBit("IsVariadic") << ");\n";
+    } else if (Arg->isSubClassOf("NTTP")) {
+      auto Type = Arg->getValueAsString("TypeName");
+
+      if (TemplateNameToParmName.find(Type.str()) ==
+          TemplateNameToParmName.end()) {
+        PrintFatalError("Unkown Type Name");
+      }
+
+      auto TSIName = "TSI" + std::to_string(PS.UniqueCounter++);
+      Code << " auto *" << TSIName << " = C.getTrivialTypeSourceInfo(QualType("
+           << TemplateNameToParmName[Type.str()] << "->getTypeForDecl(), 0));\n"
+           << " auto *" << ParmName
+           << " = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), "
+              "SourceLocation(), "
+           << PS.CurrentDepth << ", " << Position++ << ", /*Id=*/nullptr, "
+           << TSIName << "->getType(), " << Arg->getValueAsBit("IsVariadic")
+           << ", " << TSIName << ");\n";
+    } else if (Arg->isSubClassOf("BuiltinNTTP")) {
+      if (Arg->getValueAsString("TypeName") != "size_t")
+        PrintFatalError("Unkown Type Name");
+      if (!PS.EmittedSizeTInfo) {
+        Code << "TypeSourceInfo *SizeTInfo = "
+                "C.getTrivialTypeSourceInfo(C.getSizeType());\n";
+        PS.EmittedSizeTInfo = true;
+      }
+      Code << " auto *" << ParmName
+           << " = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), "
+              "SourceLocation(), "
+           << PS.CurrentDepth << ", " << Position++
+           << ", /*Id=*/nullptr, SizeTInfo->getType(), "
+              "/*ParameterPack=*/false, SizeTInfo);\n";
+    } else {
+      PrintFatalError("Unknown Argument Type");
+    }
+
+    TemplateNameToParmName[Arg->getValueAsString("Name").str()] = ParmName;
+    Params.emplace_back(std::move(ParmName));
+  }
+
+  auto TPLName = "TPL" + std::to_string(PS.UniqueCounter++);
+  Code << " auto *" << TPLName
+       << " = TemplateParameterList::Create(C, SourceLocation(), "
+          "SourceLocation(), {";
+
+  if (Params.empty()) {
+    PrintFatalError(
+        "Expected at least one argument in template parameter list");
+  }
+
+  bool First = true;
+  for (auto e : Params) {
+    if (First) {
+      First = false;
+      Code << e;
+    } else {
+      Code << ", " << e;
+    }
+  }
+  Code << "}, SourceLocation(), nullptr);\n";
+
+  return {std::move(Code).str(), std::move(TPLName)};
+}
+
+static void
+EmitCreateBuiltinTemplateParameterList(std::vector<const Record *> TemplateArgs,
+                                       StringRef Name) {
+  using namespace std::string_literals;
+  CreateBuiltinTemplateParameterList +=
+      "case BTK"s + std::string{Name} + ": {\n"s;
+
+  ParserState PS;
+  auto [Code, TPLName] = ParseTemplateParameterList(PS, TemplateArgs);
+  CreateBuiltinTemplateParameterList += Code + "\n  return " + TPLName + ";\n";
+
+  CreateBuiltinTemplateParameterList += "  }\n";
+}
+
+void EmitBuiltinTemplate(raw_ostream &OS, const Record *BuiltinTemplate) {
+  auto Name = BuiltinTemplate->getName();
+
+  std::vector<const Record *> TemplateHead =
+      BuiltinTemplate->getValueAsListOfDefs("TemplateHead");
+
+  EmitCreateBuiltinTemplateParameterList(TemplateHead, Name);
+
+  TemplateNameList += "BuiltinTemplate(";
+  TemplateNameList += Name;
+  TemplateNameList += ")\n";
+}
+} // namespace
+
+void clang::EmitClangBuiltinTemplates(const llvm::RecordKeeper &Records,
----------------
philnik777 wrote:

```c++
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|*                                                                            *|
|* Tables and code for Clang's builtin templates                              *|
|*                                                                            *|
|* Automatically generated file, do not edit!                                 *|
|*                                                                            *|
\*===----------------------------------------------------------------------===*/

#if defined(CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST)
case BTK__builtin_common_type: {
 auto *Parm1 = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(), 1, 0, /*Id=*/nullptr, /*Typename=*/false, true);
 auto *TPL2 = TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), {Parm1}, SourceLocation(), nullptr);
 auto *Parm0 = TemplateTemplateParmDecl::Create(C, DC, SourceLocation(), 0, 0, /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, TPL2);
 auto *Parm4 = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(), 1, 0, /*Id=*/nullptr, /*Typename=*/false, false);
 auto *TPL5 = TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), {Parm4}, SourceLocation(), nullptr);
 auto *Parm3 = TemplateTemplateParmDecl::Create(C, DC, SourceLocation(), 0, 1, /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, TPL5);
 auto *Parm6 = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(), 0, 2, /*Id=*/nullptr, /*Typename=*/false, false);
 auto *Parm7 = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(), 0, 3, /*Id=*/nullptr, /*Typename=*/false, true);
 auto *TPL8 = TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), {Parm0, Parm3, Parm6, Parm7}, SourceLocation(), nullptr);

  return TPL8;
  }
case BTK__make_integer_seq: {
 auto *Parm1 = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(), 1, 0, /*Id=*/nullptr, /*Typename=*/false, false);
 auto *TSI3 = C.getTrivialTypeSourceInfo(QualType(Parm1->getTypeForDecl(), 0));
 auto *Parm2 = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), SourceLocation(), 1, 1, /*Id=*/nullptr, TSI3->getType(), true, TSI3);
 auto *TPL4 = TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), {Parm1, Parm2}, SourceLocation(), nullptr);
 auto *Parm0 = TemplateTemplateParmDecl::Create(C, DC, SourceLocation(), 0, 0, /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, TPL4);
 auto *Parm5 = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(), 0, 1, /*Id=*/nullptr, /*Typename=*/false, false);
 auto *TSI7 = C.getTrivialTypeSourceInfo(QualType(Parm5->getTypeForDecl(), 0));
 auto *Parm6 = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), SourceLocation(), 0, 2, /*Id=*/nullptr, TSI7->getType(), false, TSI7);
 auto *TPL8 = TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), {Parm0, Parm5, Parm6}, SourceLocation(), nullptr);

  return TPL8;
  }
case BTK__type_pack_element: {
TypeSourceInfo *SizeTInfo = C.getTrivialTypeSourceInfo(C.getSizeType());
 auto *Parm0 = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), SourceLocation(), 0, 0, /*Id=*/nullptr, SizeTInfo->getType(), /*ParameterPack=*/false, SizeTInfo);
 auto *Parm1 = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(), 0, 1, /*Id=*/nullptr, /*Typename=*/false, true);
 auto *TPL2 = TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), {Parm0, Parm1}, SourceLocation(), nullptr);

  return TPL2;
  }
#undef CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST
#else
BuiltinTemplate(__builtin_common_type)
BuiltinTemplate(__make_integer_seq)
BuiltinTemplate(__type_pack_element)
#undef BuiltinTemplate
#endif
```


https://github.com/llvm/llvm-project/pull/123736


More information about the cfe-commits mailing list