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