brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.0 KiB · 7c0cda0 Raw
208 lines · cpp
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-exception6//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(PS.UniqueCounter++);47    if (Arg->isSubClassOf("Template")) {48      ++PS.CurrentDepth;49      auto [TemplateCode, TPLName] =50          ParseTemplateParameterList(PS, Arg->getValueAsListOfDefs("Args"));51      --PS.CurrentDepth;52      Code << TemplateCode << " auto *" << ParmName53           << " = TemplateTemplateParmDecl::Create(C, DC, SourceLocation(), "54           << PS.CurrentDepth << ", " << Position++55           << ", /*ParameterPack=*/false, /*Id=*/nullptr, "56              "/*Kind=*/TNK_Type_template, /*Typename=*/false, "57           << TPLName << ");\n";58    } else if (Arg->isSubClassOf("Class")) {59      Code << " auto *" << ParmName60           << " = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), "61              "SourceLocation(), "62           << PS.CurrentDepth << ", " << Position++63           << ", /*Id=*/nullptr, /*Typename=*/false, "64           << Arg->getValueAsBit("IsVariadic") << ");\n";65    } else if (Arg->isSubClassOf("NTTP")) {66      auto Type = Arg->getValueAsString("TypeName");67 68      if (!TemplateNameToParmName.contains(Type.str()))69        PrintFatalError("Unknown Type Name");70 71      auto TSIName = "TSI" + std::to_string(PS.UniqueCounter++);72      Code << " auto *" << TSIName << " = C.getTrivialTypeSourceInfo(QualType("73           << TemplateNameToParmName[Type.str()] << "->getTypeForDecl(), 0));\n"74           << " auto *" << ParmName75           << " = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), "76              "SourceLocation(), "77           << PS.CurrentDepth << ", " << Position++ << ", /*Id=*/nullptr, "78           << TSIName << "->getType(), " << Arg->getValueAsBit("IsVariadic")79           << ", " << TSIName << ");\n";80    } else if (Arg->isSubClassOf("BuiltinNTTP")) {81      std::string SourceInfo;82      if (Arg->getValueAsString("TypeName") == "size_t") {83        SourceInfo = "SizeTInfo";84        if (!PS.EmittedSizeTInfo) {85          Code << "TypeSourceInfo *SizeTInfo = "86                  "C.getTrivialTypeSourceInfo(C.getSizeType());\n";87          PS.EmittedSizeTInfo = true;88        }89      } else if (Arg->getValueAsString("TypeName") == "uint32_t") {90        SourceInfo = "Uint32TInfo";91        if (!PS.EmittedUint32TInfo) {92          Code << "TypeSourceInfo *Uint32TInfo = "93                  "C.getTrivialTypeSourceInfo(C.UnsignedIntTy);\n";94          PS.EmittedUint32TInfo = true;95        }96      } else {97        PrintFatalError("Unknown Type Name");98      }99      Code << " auto *" << ParmName100           << " = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), "101              "SourceLocation(), "102           << PS.CurrentDepth << ", " << Position++ << ", /*Id=*/nullptr, "103           << SourceInfo104           << "->getType(), "105              "/*ParameterPack=*/false, "106           << SourceInfo << ");\n";107    } else {108      PrintFatalError("Unknown Argument Type");109    }110 111    TemplateNameToParmName[Arg->getValueAsString("Name").str()] = ParmName;112    Params.emplace_back(std::move(ParmName));113  }114 115  auto TPLName = "TPL" + std::to_string(PS.UniqueCounter++);116  Code << " auto *" << TPLName117       << " = TemplateParameterList::Create(C, SourceLocation(), "118          "SourceLocation(), {";119 120  if (Params.empty()) {121    PrintFatalError(122        "Expected at least one argument in template parameter list");123  }124 125  bool First = true;126  for (const auto &e : Params) {127    if (First) {128      First = false;129      Code << e;130    } else {131      Code << ", " << e;132    }133  }134  Code << "}, SourceLocation(), nullptr);\n";135 136  return {std::move(Code).str(), std::move(TPLName)};137}138 139static void140EmitCreateBuiltinTemplateParameterList(std::vector<const Record *> TemplateArgs,141                                       StringRef Name) {142  using namespace std::string_literals;143  CreateBuiltinTemplateParameterList +=144      "case BTK"s + std::string{Name} + ": {\n"s;145 146  ParserState PS;147  auto [Code, TPLName] = ParseTemplateParameterList(PS, TemplateArgs);148  CreateBuiltinTemplateParameterList += Code + "\n  return " + TPLName + ";\n";149 150  CreateBuiltinTemplateParameterList += "  }\n";151}152 153void EmitBuiltinTemplate(const Record *BuiltinTemplate) {154  auto Class = BuiltinTemplate->getType()->getAsString();155  auto Name = BuiltinTemplate->getName();156 157  std::vector<const Record *> TemplateHead =158      BuiltinTemplate->getValueAsListOfDefs("TemplateHead");159 160  EmitCreateBuiltinTemplateParameterList(TemplateHead, Name);161 162  TemplateNameList += Class + "(";163  TemplateNameList += Name;164  TemplateNameList += ")\n";165 166  BuiltinClasses.insert(Class);167}168 169void EmitDefaultDefine(llvm::raw_ostream &OS, StringRef Name) {170  OS << "#ifndef " << Name << "\n";171  OS << "#define " << Name << "(NAME)" << " " << "BuiltinTemplate"172     << "(NAME)\n";173  OS << "#endif\n\n";174}175 176void EmitUndef(llvm::raw_ostream &OS, StringRef Name) {177  OS << "#undef " << Name << "\n";178}179} // namespace180 181void clang::EmitClangBuiltinTemplates(const llvm::RecordKeeper &Records,182                                      llvm::raw_ostream &OS) {183  emitSourceFileHeader("Tables and code for Clang's builtin templates", OS);184 185  for (const auto *Builtin :186       Records.getAllDerivedDefinitions("BuiltinTemplate"))187    EmitBuiltinTemplate(Builtin);188 189  for (const auto &ClassEntry : BuiltinClasses) {190    StringRef Class = ClassEntry.getKey();191    if (Class == "BuiltinTemplate")192      continue;193    EmitDefaultDefine(OS, Class);194  }195 196  OS << "#if defined(CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST)\n"197     << CreateBuiltinTemplateParameterList198     << "#undef CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST\n#else\n"199     << TemplateNameList << "#undef BuiltinTemplate\n#endif\n";200 201  for (const auto &ClassEntry : BuiltinClasses) {202    StringRef Class = ClassEntry.getKey();203    if (Class == "BuiltinTemplate")204      continue;205    EmitUndef(OS, Class);206  }207}208