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

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 19 09:53:33 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,
----------------
erichkeane wrote:

Rather than me reviewing all of this for correctness, can you paste the contents of these generated files for me?  That way I can do a quick 1x over?

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


More information about the cfe-commits mailing list