brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.0 KiB · 1e79c00 Raw
251 lines · cpp
1//===- offload-tblgen/APIGen.cpp - Tablegen backend for Offload header ----===//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 is a Tablegen backend that produces the contents of the Offload API10// header. The generated comments are Doxygen compatible.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/ADT/StringExtras.h"15#include "llvm/Support/FormatVariadic.h"16#include "llvm/TableGen/Record.h"17#include "llvm/TableGen/TableGenBackend.h"18 19#include "GenCommon.hpp"20#include "RecordTypes.hpp"21 22using namespace llvm;23using namespace offload::tblgen;24 25// Produce a possibly multi-line comment from the input string26static std::string MakeComment(StringRef in) {27  std::string out = "";28  size_t LineStart = 0;29  size_t LineBreak = 0;30  while (LineBreak < in.size()) {31    LineBreak = in.find_first_of("\n", LineStart);32    if (LineBreak - LineStart <= 1) {33      break;34    }35    out += std::string("/// ") +36           in.substr(LineStart, LineBreak - LineStart).str() + "\n";37    if (LineBreak != std::string::npos)38      LineStart = LineBreak + 1;39  }40 41  return out;42}43 44static void ProcessHandle(const HandleRec &H, raw_ostream &OS) {45  if (!H.getName().ends_with("_handle_t")) {46    errs() << "Handle type name (" << H.getName()47           << ") must end with '_handle_t'!\n";48    exit(1);49  }50 51  auto ImplName = getHandleImplName(H);52  OS << CommentsHeader;53  OS << formatv("/// @brief {0}\n", H.getDesc());54  OS << formatv("typedef struct {0} *{1};\n", ImplName, H.getName());55}56 57static void ProcessTypedef(const TypedefRec &T, raw_ostream &OS) {58  OS << CommentsHeader;59  OS << formatv("/// @brief {0}\n", T.getDesc());60  OS << formatv("typedef {0} {1};\n", T.getValue(), T.getName());61}62 63static void ProcessMacro(const MacroRec &M, raw_ostream &OS) {64  OS << CommentsHeader;65  OS << formatv("#ifndef {0}\n", M.getName());66  if (auto Condition = M.getCondition()) {67    OS << formatv("#if {0}\n", *Condition);68  }69  OS << "/// @brief " << M.getDesc() << "\n";70  OS << formatv("#define {0} {1}\n", M.getNameWithArgs(), M.getValue());71  if (auto AltValue = M.getAltValue()) {72    OS << "#else\n";73    OS << formatv("#define {0} {1}\n", M.getNameWithArgs(), *AltValue);74  }75  if (auto Condition = M.getCondition()) {76    OS << formatv("#endif // {0}\n", *Condition);77  }78  OS << formatv("#endif // {0}\n", M.getName());79}80 81static void ProcessFunction(const FunctionRec &F, raw_ostream &OS) {82  OS << CommentsHeader;83  OS << formatv("/// @brief {0}\n", F.getDesc());84  OS << CommentsBreak;85 86  OS << "/// @details\n";87  for (auto &Detail : F.getDetails()) {88    OS << formatv("///    - {0}\n", Detail);89  }90  OS << CommentsBreak;91 92  // Emit analogue remarks93  auto Analogues = F.getAnalogues();94  if (!Analogues.empty()) {95    OS << "/// @remarks\n///  _Analogues_\n";96    for (auto &Analogue : Analogues) {97      OS << formatv("///    - **{0}**\n", Analogue);98    }99    OS << CommentsBreak;100  }101 102  OS << "/// @returns\n";103  auto Returns = F.getReturns();104  for (auto &Ret : Returns) {105    OS << formatv("///     - ::{0}\n", Ret.getValue());106    auto RetConditions = Ret.getConditions();107    for (auto &RetCondition : RetConditions) {108      OS << formatv("///         + {0}\n", RetCondition);109    }110  }111 112  OS << formatv("{0}_APIEXPORT {1}_result_t {0}_APICALL ", PrefixUpper,113                PrefixLower);114  OS << F.getName();115  OS << "(\n";116  auto Params = F.getParams();117  for (auto &Param : Params) {118    OS << MakeParamComment(Param) << "\n";119    OS << "  " << Param.getType() << " " << Param.getName();120    if (Param != Params.back()) {121      OS << ",\n";122    } else {123      OS << "\n";124    }125  }126  OS << ");\n\n";127}128 129static void ProcessEnum(const EnumRec &Enum, raw_ostream &OS) {130  OS << CommentsHeader;131  OS << formatv("/// @brief {0}\n", Enum.getDesc());132  OS << formatv("typedef enum {0} {{\n", Enum.getName());133 134  // Bitfields start from 1, other enums from 0135  uint32_t EtorVal = Enum.isBitField();136  for (const auto &EnumVal : Enum.getValues()) {137    if (Enum.isTyped()) {138      OS << MakeComment(139          formatv("[{0}] {1}", EnumVal.getTaggedType(), EnumVal.getDesc())140              .str());141    } else {142      OS << MakeComment(EnumVal.getDesc());143    }144    OS << formatv(TAB_1 "{0}_{1} = {2},\n", Enum.getEnumValNamePrefix(),145                  EnumVal.getName(), EtorVal);146    if (Enum.isBitField()) {147      EtorVal <<= 1u;148    } else {149      ++EtorVal;150    }151  }152 153  // Add last_element/force uint32 val154  OS << formatv(TAB_1 "/// @cond\n" TAB_1 "{0}_LAST = {1},\n" TAB_1155                      "{0}_FORCE_UINT32 = 0x7fffffff\n" TAB_1156                      "/// @endcond\n\n",157                Enum.getEnumValNamePrefix(), EtorVal);158 159  OS << formatv("} {0};\n", Enum.getName());160}161 162static void ProcessStruct(const StructRec &Struct, raw_ostream &OS) {163  OS << CommentsHeader;164  OS << formatv("/// @brief {0}\n", Struct.getDesc());165  OS << formatv("typedef struct {0} {{\n", Struct.getName());166 167  for (const auto &Member : Struct.getMembers()) {168    OS << formatv(TAB_1 "{0} {1}; {2}", Member.getType(), Member.getName(),169                  MakeComment(Member.getDesc()));170  }171 172  OS << formatv("} {0};\n\n", Struct.getName());173}174 175static void ProcessFptrTypedef(const FptrTypedefRec &F, raw_ostream &OS) {176  OS << CommentsHeader;177  OS << formatv("/// @brief {0}\n", F.getDesc());178  OS << formatv("typedef {0} (*{1})(", F.getReturn(), F.getName());179  for (const auto &Param : F.getParams()) {180    OS << formatv("\n  // {0}\n  {1} {2}", Param.getDesc(), Param.getType(),181                  Param.getName());182    if (Param != F.getParams().back())183      OS << ",";184  }185  OS << ");\n";186}187 188static void ProcessFuncParamStruct(const FunctionRec &Func, raw_ostream &OS) {189  if (Func.getParams().size() == 0) {190    return;191  }192 193  auto FuncParamStructBegin = R"(194///////////////////////////////////////////////////////////////////////////////195/// @brief Function parameters for {0}196/// @details Each entry is a pointer to the parameter passed to the function;197typedef struct {1} {{198)";199 200  OS << formatv(FuncParamStructBegin, Func.getName(),201                Func.getParamStructName());202  for (const auto &Param : Func.getParams()) {203    OS << TAB_1 << Param.getType() << "* p" << Param.getName() << ";\n";204  }205  OS << formatv("} {0};\n", Func.getParamStructName());206}207 208static void ProcessFuncWithCodeLocVariant(const FunctionRec &Func,209                                          raw_ostream &OS) {210 211  auto FuncWithCodeLocBegin = R"(212///////////////////////////////////////////////////////////////////////////////213/// @brief Variant of {0} that also sets source code location information214/// @details See also ::{0}215OL_APIEXPORT ol_result_t OL_APICALL {0}WithCodeLoc(216)";217  OS << formatv(FuncWithCodeLocBegin, Func.getName());218  auto Params = Func.getParams();219  for (auto &Param : Params) {220    OS << "  " << Param.getType() << " " << Param.getName();221    OS << ",\n";222  }223  OS << "ol_code_location_t *CodeLocation);\n\n";224}225 226void EmitOffloadAPI(const RecordKeeper &Records, raw_ostream &OS) {227  OS << GenericHeader;228  OS << FileHeader;229 230  // Generate main API definitions231  for (auto *R : Records.getAllDerivedDefinitions("Macro"))232    ProcessMacro(MacroRec{R}, OS);233  for (auto *R : Records.getAllDerivedDefinitions("Handle"))234    ProcessHandle(HandleRec{R}, OS);235  for (auto *R : Records.getAllDerivedDefinitions("Enum"))236    ProcessEnum(EnumRec{R}, OS);237  for (auto *R : Records.getAllDerivedDefinitions("Typedef"))238    ProcessTypedef(TypedefRec{R}, OS);239  for (auto *R : Records.getAllDerivedDefinitions("FptrTypedef"))240    ProcessFptrTypedef(FptrTypedefRec{R}, OS);241  for (auto *R : Records.getAllDerivedDefinitions("Struct"))242    ProcessStruct(StructRec{R}, OS);243  for (auto *R : Records.getAllDerivedDefinitions("Function")) {244    ProcessFuncParamStruct(FunctionRec{R}, OS);245    ProcessFunction(FunctionRec{R}, OS);246    ProcessFuncWithCodeLocVariant(FunctionRec{R}, OS);247  }248 249  OS << FileFooter;250}251