[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