Path: blob/main/contrib/llvm-project/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp
213766 views
//=- ClangBuiltinsEmitter.cpp - Generate Clang builtin templates-*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This tablegen backend emits Clang's builtin templates.9//10//===----------------------------------------------------------------------===//1112#include "TableGenBackends.h"13#include "llvm/ADT/StringSet.h"14#include "llvm/TableGen/Error.h"15#include "llvm/TableGen/TableGenBackend.h"1617#include <sstream>1819using namespace llvm;2021static std::string TemplateNameList;22static std::string CreateBuiltinTemplateParameterList;2324static llvm::StringSet<> BuiltinClasses;2526namespace {27struct ParserState {28size_t UniqueCounter = 0;29size_t CurrentDepth = 0;30bool EmittedSizeTInfo = false;31bool EmittedUint32TInfo = false;32};3334std::pair<std::string, std::string>35ParseTemplateParameterList(ParserState &PS,36ArrayRef<const Record *> TemplateArgs) {37llvm::SmallVector<std::string, 4> Params;38llvm::StringMap<std::string> TemplateNameToParmName;3940std::ostringstream Code;41Code << std::boolalpha;4243size_t Position = 0;44for (const Record *Arg : TemplateArgs) {45std::string ParmName = "Parm" + std::to_string(PS.UniqueCounter++);46if (Arg->isSubClassOf("Template")) {47++PS.CurrentDepth;48auto [TemplateCode, TPLName] =49ParseTemplateParameterList(PS, Arg->getValueAsListOfDefs("Args"));50--PS.CurrentDepth;51Code << TemplateCode << " auto *" << ParmName52<< " = TemplateTemplateParmDecl::Create(C, DC, SourceLocation(), "53<< PS.CurrentDepth << ", " << Position++54<< ", /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, "55<< TPLName << ");\n";56} else if (Arg->isSubClassOf("Class")) {57Code << " auto *" << ParmName58<< " = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), "59"SourceLocation(), "60<< PS.CurrentDepth << ", " << Position++61<< ", /*Id=*/nullptr, /*Typename=*/false, "62<< Arg->getValueAsBit("IsVariadic") << ");\n";63} else if (Arg->isSubClassOf("NTTP")) {64auto Type = Arg->getValueAsString("TypeName");6566if (!TemplateNameToParmName.contains(Type.str()))67PrintFatalError("Unknown Type Name");6869auto TSIName = "TSI" + std::to_string(PS.UniqueCounter++);70Code << " auto *" << TSIName << " = C.getTrivialTypeSourceInfo(QualType("71<< TemplateNameToParmName[Type.str()] << "->getTypeForDecl(), 0));\n"72<< " auto *" << ParmName73<< " = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), "74"SourceLocation(), "75<< PS.CurrentDepth << ", " << Position++ << ", /*Id=*/nullptr, "76<< TSIName << "->getType(), " << Arg->getValueAsBit("IsVariadic")77<< ", " << TSIName << ");\n";78} else if (Arg->isSubClassOf("BuiltinNTTP")) {79std::string SourceInfo;80if (Arg->getValueAsString("TypeName") == "size_t") {81SourceInfo = "SizeTInfo";82if (!PS.EmittedSizeTInfo) {83Code << "TypeSourceInfo *SizeTInfo = "84"C.getTrivialTypeSourceInfo(C.getSizeType());\n";85PS.EmittedSizeTInfo = true;86}87} else if (Arg->getValueAsString("TypeName") == "uint32_t") {88SourceInfo = "Uint32TInfo";89if (!PS.EmittedUint32TInfo) {90Code << "TypeSourceInfo *Uint32TInfo = "91"C.getTrivialTypeSourceInfo(C.UnsignedIntTy);\n";92PS.EmittedUint32TInfo = true;93}94} else {95PrintFatalError("Unknown Type Name");96}97Code << " auto *" << ParmName98<< " = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), "99"SourceLocation(), "100<< PS.CurrentDepth << ", " << Position++ << ", /*Id=*/nullptr, "101<< SourceInfo102<< "->getType(), "103"/*ParameterPack=*/false, "104<< SourceInfo << ");\n";105} else {106PrintFatalError("Unknown Argument Type");107}108109TemplateNameToParmName[Arg->getValueAsString("Name").str()] = ParmName;110Params.emplace_back(std::move(ParmName));111}112113auto TPLName = "TPL" + std::to_string(PS.UniqueCounter++);114Code << " auto *" << TPLName115<< " = TemplateParameterList::Create(C, SourceLocation(), "116"SourceLocation(), {";117118if (Params.empty()) {119PrintFatalError(120"Expected at least one argument in template parameter list");121}122123bool First = true;124for (const auto &e : Params) {125if (First) {126First = false;127Code << e;128} else {129Code << ", " << e;130}131}132Code << "}, SourceLocation(), nullptr);\n";133134return {std::move(Code).str(), std::move(TPLName)};135}136137static void138EmitCreateBuiltinTemplateParameterList(std::vector<const Record *> TemplateArgs,139StringRef Name) {140using namespace std::string_literals;141CreateBuiltinTemplateParameterList +=142"case BTK"s + std::string{Name} + ": {\n"s;143144ParserState PS;145auto [Code, TPLName] = ParseTemplateParameterList(PS, TemplateArgs);146CreateBuiltinTemplateParameterList += Code + "\n return " + TPLName + ";\n";147148CreateBuiltinTemplateParameterList += " }\n";149}150151void EmitBuiltinTemplate(const Record *BuiltinTemplate) {152auto Class = BuiltinTemplate->getType()->getAsString();153auto Name = BuiltinTemplate->getName();154155std::vector<const Record *> TemplateHead =156BuiltinTemplate->getValueAsListOfDefs("TemplateHead");157158EmitCreateBuiltinTemplateParameterList(TemplateHead, Name);159160TemplateNameList += Class + "(";161TemplateNameList += Name;162TemplateNameList += ")\n";163164BuiltinClasses.insert(Class);165}166167void EmitDefaultDefine(llvm::raw_ostream &OS, StringRef Name) {168OS << "#ifndef " << Name << "\n";169OS << "#define " << Name << "(NAME)" << " " << "BuiltinTemplate"170<< "(NAME)\n";171OS << "#endif\n\n";172}173174void EmitUndef(llvm::raw_ostream &OS, StringRef Name) {175OS << "#undef " << Name << "\n";176}177} // namespace178179void clang::EmitClangBuiltinTemplates(const llvm::RecordKeeper &Records,180llvm::raw_ostream &OS) {181emitSourceFileHeader("Tables and code for Clang's builtin templates", OS);182183for (const auto *Builtin :184Records.getAllDerivedDefinitions("BuiltinTemplate"))185EmitBuiltinTemplate(Builtin);186187for (const auto &ClassEntry : BuiltinClasses) {188StringRef Class = ClassEntry.getKey();189if (Class == "BuiltinTemplate")190continue;191EmitDefaultDefine(OS, Class);192}193194OS << "#if defined(CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST)\n"195<< CreateBuiltinTemplateParameterList196<< "#undef CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST\n#else\n"197<< TemplateNameList << "#undef BuiltinTemplate\n#endif\n";198199for (const auto &ClassEntry : BuiltinClasses) {200StringRef Class = ClassEntry.getKey();201if (Class == "BuiltinTemplate")202continue;203EmitUndef(OS, Class);204}205}206207208