brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.9 KiB · 4f76100 Raw
170 lines · cpp
1//===- offload-tblgen/EntryPointGen.cpp - Tablegen backend for Offload ----===//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 actual entry points for the10// Offload API. It serves as a place to integrate functionality like tracing11// and validation before dispatching to the actual implementations.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 23static void EmitValidationFunc(const FunctionRec &F, raw_ostream &OS) {24  OS << CommentsHeader;25  // Emit preamble26  OS << formatv("llvm::Error {0}_val(\n  ", F.getName());27  // Emit arguments28  std::string ParamNameList = "";29  for (auto &Param : F.getParams()) {30    OS << Param.getType() << " " << Param.getName();31    if (Param != F.getParams().back()) {32      OS << ", ";33    }34    ParamNameList += Param.getName().str() + ", ";35  }36  OS << ") {\n";37 38  bool HasValidation = llvm::any_of(F.getReturns(), [](auto &R) {39    return llvm::any_of(R.getConditions(), [](auto &C) {40      return C.starts_with("`") && C.ends_with("`");41    });42  });43 44  if (HasValidation) {45    OS << TAB_1 "if (llvm::offload::isValidationEnabled()) {\n";46    // Emit validation checks47    for (const auto &Return : F.getReturns()) {48      for (auto &Condition : Return.getConditions()) {49        if (Condition.starts_with("`") && Condition.ends_with("`")) {50          auto ConditionString = Condition.substr(1, Condition.size() - 2);51          OS << formatv(TAB_2 "if ({0}) {{\n", ConditionString);52          OS << formatv(TAB_353                        "return createOffloadError(error::ErrorCode::{0}, "54                        "\"validation failure: {1}\");\n",55                        Return.getUnprefixedValue(), ConditionString);56          OS << TAB_2 "}\n\n";57        }58      }59    }60    OS << TAB_1 "}\n\n";61  }62 63  // Perform actual function call to the implementation64  ParamNameList = ParamNameList.substr(0, ParamNameList.size() - 2);65  OS << formatv(TAB_1 "return llvm::offload::{0}_impl({1});\n\n", F.getName(),66                ParamNameList);67  OS << "}\n";68}69 70static void EmitEntryPointFunc(const FunctionRec &F, raw_ostream &OS) {71  // Emit preamble72  OS << formatv("{1}_APIEXPORT {0}_result_t {1}_APICALL {2}(\n  ", PrefixLower,73                PrefixUpper, F.getName());74  // Emit arguments75  std::string ParamNameList = "";76  for (auto &Param : F.getParams()) {77    OS << Param.getType() << " " << Param.getName();78    if (Param != F.getParams().back()) {79      OS << ", ";80    }81    ParamNameList += Param.getName().str() + ", ";82  }83  OS << ") {\n";84 85  // Check offload is initialized86  if (F.getName() != "olInit") {87    OS << "if (!llvm::offload::isOffloadInitialized()) return &UninitError;";88 89    // Emit pre-call prints90    // Postpone pre-calls for olInit as tracing requires liboffload to be initialized91    OS << TAB_1 "if (llvm::offload::isTracingEnabled()) {\n";92    OS << formatv(TAB_2 "llvm::errs() << \"---> {0}\";\n", F.getName());93    OS << TAB_1 "}\n\n";94  }95 96  // Perform actual function call to the validation wrapper97  ParamNameList = ParamNameList.substr(0, ParamNameList.size() - 2);98  OS << formatv(99      TAB_1 "{0}_result_t Result = llvmErrorToOffloadError({1}_val({2}));\n\n",100      PrefixLower, F.getName(), ParamNameList);101 102  // Emit post-call prints103  OS << TAB_1 "if (llvm::offload::isTracingEnabled()) {\n";104  // postponed pre-call print for olInit105  if (F.getName() == "olInit")106    OS << formatv(TAB_2 "llvm::errs() << \"---> {0}\";\n", F.getName());107 108  if (F.getParams().size() > 0) {109    OS << formatv(TAB_2 "{0} Params = {{", F.getParamStructName());110    for (const auto &Param : F.getParams()) {111      OS << "&" << Param.getName();112      if (Param != F.getParams().back()) {113        OS << ", ";114      }115    }116    OS << formatv("};\n");117    OS << TAB_2 "llvm::errs() << \"(\" << &Params << \")\";\n";118  } else {119    OS << TAB_2 "llvm::errs() << \"()\";\n";120  }121  OS << TAB_2 "llvm::errs() << \"-> \" << Result << \"\\n\";\n";122  OS << TAB_2 "if (Result && Result->Details) {\n";123  OS << TAB_3 "llvm::errs() << \"     *Error Details* \" << Result->Details "124              "<< \" \\n\";\n";125  OS << TAB_2 "}\n";126  OS << TAB_1 "}\n";127 128  OS << TAB_1 "return Result;\n";129  OS << "}\n";130}131 132static void EmitCodeLocWrapper(const FunctionRec &F, raw_ostream &OS) {133  // Emit preamble134  OS << formatv("{0}_result_t {1}WithCodeLoc(\n  ", PrefixLower, F.getName());135  // Emit arguments136  std::string ParamNameList = "";137  for (auto &Param : F.getParams()) {138    OS << Param.getType() << " " << Param.getName() << ", ";139    ParamNameList += Param.getName().str();140    if (Param != F.getParams().back()) {141      ParamNameList += ", ";142    }143  }144  OS << "ol_code_location_t *CodeLocation";145  OS << ") {\n";146  OS << TAB_1 "currentCodeLocation() = CodeLocation;\n";147  OS << formatv(TAB_1 "{0}_result_t Result = ::{1}({2});\n\n", PrefixLower,148                F.getName(), ParamNameList);149  OS << TAB_1 "currentCodeLocation() = nullptr;\n";150  OS << TAB_1 "return Result;\n";151  OS << "}\n";152}153 154void EmitOffloadEntryPoints(const RecordKeeper &Records, raw_ostream &OS) {155  OS << GenericHeader;156 157  constexpr const char *UninitMessage =158      "liboffload has not been initialized - please call olInit before using "159      "this API";160  OS << formatv("static {0}_error_struct_t UninitError = "161                "{{{1}_ERRC_UNINITIALIZED, \"{2}\"};",162                PrefixLower, PrefixUpper, UninitMessage);163 164  for (auto *R : Records.getAllDerivedDefinitions("Function")) {165    EmitValidationFunc(FunctionRec{R}, OS);166    EmitEntryPointFunc(FunctionRec{R}, OS);167    EmitCodeLocWrapper(FunctionRec{R}, OS);168  }169}170