brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.7 KiB · 89d7c82 Raw
270 lines · cpp
1//===- offload-tblgen/APIGen.cpp - Tablegen backend for Offload printing --===//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 print functions for the Offload API10// entry point functions.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/Support/FormatVariadic.h"15#include "llvm/TableGen/Record.h"16 17#include "GenCommon.hpp"18#include "RecordTypes.hpp"19 20using namespace llvm;21using namespace offload::tblgen;22 23constexpr auto PrintTypeHeader =24    R"(///////////////////////////////////////////////////////////////////////////////25/// @brief Print operator for the {0} type26/// @returns llvm::raw_ostream &27)";28 29constexpr auto PrintTaggedEnumHeader =30    R"(///////////////////////////////////////////////////////////////////////////////31/// @brief Print type-tagged {0} enum value32/// @returns llvm::raw_ostream &33)";34 35static void ProcessEnum(const EnumRec &Enum, raw_ostream &OS) {36  OS << formatv(PrintTypeHeader, Enum.getName());37  OS << formatv("inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, "38                "enum {0} value) "39                "{{\n" TAB_1 "switch (value) {{\n",40                Enum.getName());41 42  for (const auto &Val : Enum.getValues()) {43    auto Name = Enum.getEnumValNamePrefix() + "_" + Val.getName();44    OS << formatv(TAB_1 "case {0}:\n", Name);45    OS << formatv(TAB_2 "os << \"{0}\";\n", Name);46    OS << formatv(TAB_2 "break;\n");47  }48 49  OS << TAB_1 "default:\n" TAB_2 "os << \"unknown enumerator\";\n" TAB_250              "break;\n" TAB_1 "}\n" TAB_1 "return os;\n}\n\n";51 52  if (!Enum.isTyped()) {53    return;54  }55 56  OS << formatv(PrintTaggedEnumHeader, Enum.getName());57 58  OS << formatv(R"""(template <>59inline void printTagged(llvm::raw_ostream &os, const void *ptr, {0} value, size_t size) {{60  if (ptr == NULL) {{61    printPtr(os, ptr);62    return;63  }64 65  switch (value) {{66)""",67                Enum.getName());68 69  for (const auto &Val : Enum.getValues()) {70    auto Name = Enum.getEnumValNamePrefix() + "_" + Val.getName();71    auto Type = Val.getTaggedType();72    OS << formatv(TAB_1 "case {0}: {{\n", Name);73    // Special case for strings74    if (Type == "char[]") {75      OS << formatv(TAB_2 "printPtr(os, (const char*) ptr);\n");76    } else {77      if (Type == "void *")78        OS << formatv(TAB_2 "void * const * const tptr = (void * "79                            "const * const)ptr;\n");80      else81        OS << formatv(82            TAB_2 "const {0} * const tptr = (const {0} * const)ptr;\n", Type);83      // TODO: Handle other cases here84      OS << TAB_2 "os << (const void *)tptr << \" (\";\n";85      if (Type.ends_with("*")) {86        OS << TAB_2 "os << printPtr(os, tptr);\n";87      } else {88        OS << TAB_2 "os << *tptr;\n";89      }90      OS << TAB_2 "os << \")\";\n";91    }92    OS << formatv(TAB_2 "break;\n" TAB_1 "}\n");93  }94 95  OS << TAB_1 "default:\n" TAB_2 "os << \"unknown enumerator\";\n" TAB_296              "break;\n" TAB_1 "}\n";97 98  OS << "}\n";99}100 101static void EmitResultPrint(raw_ostream &OS) {102  OS << R""(103inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,104                                const ol_error_struct_t *Err) {105  if (Err == nullptr) {106    os << "OL_SUCCESS";107  } else {108    os << Err->Code;109  }110  return os;111}112)"";113}114 115static void EmitFunctionParamStructPrint(const FunctionRec &Func,116                                         raw_ostream &OS) {117  if (Func.getParams().size() == 0) {118    return;119  }120 121  OS << formatv(R"(122inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const struct {0} *params) {{123)",124                Func.getParamStructName());125 126  for (const auto &Param : Func.getParams()) {127    OS << formatv(TAB_1 "os << \".{0} = \";\n", Param.getName());128    if (auto Range = Param.getRange()) {129      OS << formatv(TAB_1 "os << \"{{\";\n");130      OS << formatv(TAB_1 "for (size_t i = {0}; i < *params->p{1}; i++) {{\n",131                    Range->first, Range->second);132      OS << TAB_2 "if (i > 0) {\n";133      OS << TAB_3 " os << \", \";\n";134      OS << TAB_2 "}\n";135      OS << formatv(TAB_2 "printPtr(os, (*params->p{0})[i]);\n",136                    Param.getName());137      OS << formatv(TAB_1 "}\n");138      OS << formatv(TAB_1 "os << \"}\";\n");139    } else if (auto TypeInfo = Param.getTypeInfo()) {140      OS << formatv(141          TAB_1142          "printTagged(os, *params->p{0}, *params->p{1}, *params->p{2});\n",143          Param.getName(), TypeInfo->first, TypeInfo->second);144    } else if (Param.isPointerType() || Param.isHandleType()) {145      OS << formatv(TAB_1 "printPtr(os, *params->p{0});\n", Param.getName());146    } else if (Param.isFptrType()) {147      OS << formatv(TAB_1 "os << reinterpret_cast<void*>(*params->p{0});\n",148                    Param.getName());149    } else {150      OS << formatv(TAB_1 "os << *params->p{0};\n", Param.getName());151    }152    if (Param != Func.getParams().back()) {153      OS << TAB_1 "os << \", \";\n";154    }155  }156 157  OS << TAB_1 "return os;\n}\n";158}159 160void ProcessStruct(const StructRec &Struct, raw_ostream &OS) {161  if (Struct.getName() == "ol_error_struct_t") {162    return;163  }164  OS << formatv(PrintTypeHeader, Struct.getName());165  OS << formatv(R"(166inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const struct {0} params) {{167)",168                Struct.getName());169  OS << formatv(TAB_1 "os << \"(struct {0}){{\";\n", Struct.getName());170  for (const auto &Member : Struct.getMembers()) {171    OS << formatv(TAB_1 "os << \".{0} = \";\n", Member.getName());172    if (Member.isPointerType() || Member.isHandleType()) {173      OS << formatv(TAB_1 "printPtr(os, params.{0});\n", Member.getName());174    } else {175      OS << formatv(TAB_1 "os << params.{0};\n", Member.getName());176    }177    if (Member.getName() != Struct.getMembers().back().getName()) {178      OS << TAB_1 "os << \", \";\n";179    }180  }181  OS << TAB_1 "os << \"}\";\n";182  OS << TAB_1 "return os;\n";183  OS << "}\n";184}185 186void EmitOffloadPrintHeader(const RecordKeeper &Records, raw_ostream &OS) {187  OS << GenericHeader;188  OS << R"""(189// Auto-generated file, do not manually edit.190 191#pragma once192 193#include <OffloadAPI.h>194#include <llvm/Support/raw_ostream.h>195 196 197template <typename T> inline ol_result_t printPtr(llvm::raw_ostream &os, const T *ptr);198template <typename T> inline void printTagged(llvm::raw_ostream &os, const void *ptr, T value, size_t size);199)""";200 201  // ==========202  OS << "template <typename T> struct is_handle : std::false_type {};\n";203  for (auto *R : Records.getAllDerivedDefinitions("Handle")) {204    HandleRec H{R};205    OS << formatv("template <> struct is_handle<{0}> : std::true_type {{};\n",206                  H.getName());207  }208  OS << "template <typename T> inline constexpr bool is_handle_v = "209        "is_handle<T>::value;\n";210  // =========211 212  // Forward declare the operator<< overloads so their implementations can213  // use each other.214  OS << "\n";215  for (auto *R : Records.getAllDerivedDefinitions("Enum")) {216    OS << formatv("inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, "217                  "enum {0} value);\n",218                  EnumRec{R}.getName());219  }220  for (auto *R : Records.getAllDerivedDefinitions("Struct")) {221    OS << formatv("inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, "222                  "const struct {0} param);\n",223                  StructRec{R}.getName());224  }225  OS << "\n";226 227  // Create definitions228  for (auto *R : Records.getAllDerivedDefinitions("Enum")) {229    EnumRec E{R};230    ProcessEnum(E, OS);231  }232  EmitResultPrint(OS);233 234  for (auto *R : Records.getAllDerivedDefinitions("Struct")) {235    StructRec S{R};236    ProcessStruct(S, OS);237  }238 239  // Emit print functions for the function param structs240  for (auto *R : Records.getAllDerivedDefinitions("Function")) {241    EmitFunctionParamStructPrint(FunctionRec{R}, OS);242  }243 244  OS << R"""(245///////////////////////////////////////////////////////////////////////////////246// @brief Print pointer value247template <typename T> inline ol_result_t printPtr(llvm::raw_ostream &os, const T *ptr) {248    if (ptr == nullptr) {249        os << "nullptr";250    } else if constexpr (std::is_pointer_v<T>) {251        os << (const void *)(ptr) << " (";252        printPtr(os, *ptr);253        os << ")";254    } else if constexpr (std::is_void_v<T> || is_handle_v<T *>) {255        os << (const void *)ptr;256    } else if constexpr (std::is_same_v<std::remove_cv_t< T >, char>) {257        os << (const void *)(ptr) << " (";258        os << ptr;259        os << ")";260    } else {261        os << (const void *)(ptr) << " (";262        os << *ptr;263        os << ")";264    }265 266    return OL_SUCCESS;267}268  )""";269}270