1//=- ClangBuiltinsEmitter.cpp - Generate Clang builtin templates-*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This tablegen backend emits Clang's builtin templates.
10//
11//===----------------------------------------------------------------------===//
12
13#include "TableGenBackends.h"
14#include "llvm/ADT/StringSet.h"
15#include "llvm/TableGen/Error.h"
16#include "llvm/TableGen/TableGenBackend.h"
17
18#include <sstream>
19
20using namespace llvm;
21
22static std::string TemplateNameList;
23static std::string CreateBuiltinTemplateParameterList;
24
25static llvm::StringSet<> BuiltinClasses;
26
27namespace {
28struct ParserState {
29 size_t UniqueCounter = 0;
30 size_t CurrentDepth = 0;
31 bool EmittedSizeTInfo = false;
32 bool EmittedUint32TInfo = false;
33};
34
35std::pair<std::string, std::string>
36ParseTemplateParameterList(ParserState &PS,
37 ArrayRef<const Record *> TemplateArgs) {
38 llvm::SmallVector<std::string, 4> Params;
39 llvm::StringMap<std::string> TemplateNameToParmName;
40
41 std::ostringstream Code;
42 Code << std::boolalpha;
43
44 size_t Position = 0;
45 for (const Record *Arg : TemplateArgs) {
46 std::string ParmName = "Parm" + std::to_string(val: PS.UniqueCounter++);
47 if (Arg->isSubClassOf(Name: "Template")) {
48 ++PS.CurrentDepth;
49 auto [TemplateCode, TPLName] =
50 ParseTemplateParameterList(PS, TemplateArgs: Arg->getValueAsListOfDefs(FieldName: "Args"));
51 --PS.CurrentDepth;
52 Code << TemplateCode << " auto *" << ParmName
53 << " = TemplateTemplateParmDecl::Create(C, DC, SourceLocation(), "
54 << PS.CurrentDepth << ", " << Position++
55 << ", /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, "
56 << TPLName << ");\n";
57 } else if (Arg->isSubClassOf(Name: "Class")) {
58 Code << " auto *" << ParmName
59 << " = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), "
60 "SourceLocation(), "
61 << PS.CurrentDepth << ", " << Position++
62 << ", /*Id=*/nullptr, /*Typename=*/false, "
63 << Arg->getValueAsBit(FieldName: "IsVariadic") << ");\n";
64 } else if (Arg->isSubClassOf(Name: "NTTP")) {
65 auto Type = Arg->getValueAsString(FieldName: "TypeName");
66
67 if (!TemplateNameToParmName.contains(Key: Type.str()))
68 PrintFatalError(Msg: "Unknown Type Name");
69
70 auto TSIName = "TSI" + std::to_string(val: PS.UniqueCounter++);
71 Code << " auto *" << TSIName << " = C.getTrivialTypeSourceInfo(QualType("
72 << TemplateNameToParmName[Type.str()] << "->getTypeForDecl(), 0));\n"
73 << " auto *" << ParmName
74 << " = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), "
75 "SourceLocation(), "
76 << PS.CurrentDepth << ", " << Position++ << ", /*Id=*/nullptr, "
77 << TSIName << "->getType(), " << Arg->getValueAsBit(FieldName: "IsVariadic")
78 << ", " << TSIName << ");\n";
79 } else if (Arg->isSubClassOf(Name: "BuiltinNTTP")) {
80 std::string SourceInfo;
81 if (Arg->getValueAsString(FieldName: "TypeName") == "size_t") {
82 SourceInfo = "SizeTInfo";
83 if (!PS.EmittedSizeTInfo) {
84 Code << "TypeSourceInfo *SizeTInfo = "
85 "C.getTrivialTypeSourceInfo(C.getSizeType());\n";
86 PS.EmittedSizeTInfo = true;
87 }
88 } else if (Arg->getValueAsString(FieldName: "TypeName") == "uint32_t") {
89 SourceInfo = "Uint32TInfo";
90 if (!PS.EmittedUint32TInfo) {
91 Code << "TypeSourceInfo *Uint32TInfo = "
92 "C.getTrivialTypeSourceInfo(C.UnsignedIntTy);\n";
93 PS.EmittedUint32TInfo = true;
94 }
95 } else {
96 PrintFatalError(Msg: "Unknown Type Name");
97 }
98 Code << " auto *" << ParmName
99 << " = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), "
100 "SourceLocation(), "
101 << PS.CurrentDepth << ", " << Position++ << ", /*Id=*/nullptr, "
102 << SourceInfo
103 << "->getType(), "
104 "/*ParameterPack=*/false, "
105 << SourceInfo << ");\n";
106 } else {
107 PrintFatalError(Msg: "Unknown Argument Type");
108 }
109
110 TemplateNameToParmName[Arg->getValueAsString(FieldName: "Name").str()] = ParmName;
111 Params.emplace_back(Args: std::move(ParmName));
112 }
113
114 auto TPLName = "TPL" + std::to_string(val: PS.UniqueCounter++);
115 Code << " auto *" << TPLName
116 << " = TemplateParameterList::Create(C, SourceLocation(), "
117 "SourceLocation(), {";
118
119 if (Params.empty()) {
120 PrintFatalError(
121 Msg: "Expected at least one argument in template parameter list");
122 }
123
124 bool First = true;
125 for (const auto &e : Params) {
126 if (First) {
127 First = false;
128 Code << e;
129 } else {
130 Code << ", " << e;
131 }
132 }
133 Code << "}, SourceLocation(), nullptr);\n";
134
135 return {std::move(Code).str(), std::move(TPLName)};
136}
137
138static void
139EmitCreateBuiltinTemplateParameterList(std::vector<const Record *> TemplateArgs,
140 StringRef Name) {
141 using namespace std::string_literals;
142 CreateBuiltinTemplateParameterList +=
143 "case BTK"s + std::string{Name} + ": {\n"s;
144
145 ParserState PS;
146 auto [Code, TPLName] = ParseTemplateParameterList(PS, TemplateArgs);
147 CreateBuiltinTemplateParameterList += Code + "\n return " + TPLName + ";\n";
148
149 CreateBuiltinTemplateParameterList += " }\n";
150}
151
152void EmitBuiltinTemplate(const Record *BuiltinTemplate) {
153 auto Class = BuiltinTemplate->getType()->getAsString();
154 auto Name = BuiltinTemplate->getName();
155
156 std::vector<const Record *> TemplateHead =
157 BuiltinTemplate->getValueAsListOfDefs(FieldName: "TemplateHead");
158
159 EmitCreateBuiltinTemplateParameterList(TemplateArgs: TemplateHead, Name);
160
161 TemplateNameList += Class + "(";
162 TemplateNameList += Name;
163 TemplateNameList += ")\n";
164
165 BuiltinClasses.insert(key: Class);
166}
167
168void EmitDefaultDefine(llvm::raw_ostream &OS, StringRef Name) {
169 OS << "#ifndef " << Name << "\n";
170 OS << "#define " << Name << "(NAME)" << " " << "BuiltinTemplate"
171 << "(NAME)\n";
172 OS << "#endif\n\n";
173}
174
175void EmitUndef(llvm::raw_ostream &OS, StringRef Name) {
176 OS << "#undef " << Name << "\n";
177}
178} // namespace
179
180void clang::EmitClangBuiltinTemplates(const llvm::RecordKeeper &Records,
181 llvm::raw_ostream &OS) {
182 emitSourceFileHeader(Desc: "Tables and code for Clang's builtin templates", OS);
183
184 for (const auto *Builtin :
185 Records.getAllDerivedDefinitions(ClassName: "BuiltinTemplate"))
186 EmitBuiltinTemplate(BuiltinTemplate: Builtin);
187
188 for (const auto &ClassEntry : BuiltinClasses) {
189 StringRef Class = ClassEntry.getKey();
190 if (Class == "BuiltinTemplate")
191 continue;
192 EmitDefaultDefine(OS, Name: Class);
193 }
194
195 OS << "#if defined(CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST)\n"
196 << CreateBuiltinTemplateParameterList
197 << "#undef CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST\n#else\n"
198 << TemplateNameList << "#undef BuiltinTemplate\n#endif\n";
199
200 for (const auto &ClassEntry : BuiltinClasses) {
201 StringRef Class = ClassEntry.getKey();
202 if (Class == "BuiltinTemplate")
203 continue;
204 EmitUndef(OS, Name: Class);
205 }
206}
207

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp