brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.3 KiB · 68d82cb Raw
379 lines · c
1//===- ErrorReporting.h - Helper to provide nice error messages ----- 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//===----------------------------------------------------------------------===//10 11#ifndef OFFLOAD_PLUGINS_NEXTGEN_COMMON_ERROR_REPORTING_H12#define OFFLOAD_PLUGINS_NEXTGEN_COMMON_ERROR_REPORTING_H13 14#include "PluginInterface.h"15#include "Shared/EnvironmentVar.h"16 17#include "llvm/ADT/STLExtras.h"18#include "llvm/ADT/SmallString.h"19#include "llvm/ADT/StringRef.h"20#include "llvm/Frontend/OpenMP/OMP.h"21#include "llvm/Support/ErrorHandling.h"22#include "llvm/Support/WithColor.h"23#include "llvm/Support/raw_ostream.h"24 25#include <cstdint>26#include <cstdio>27#include <cstdlib>28#include <functional>29#include <optional>30#include <string>31#include <unistd.h>32 33namespace llvm {34namespace omp {35namespace target {36namespace plugin {37 38class ErrorReporter {39 40  enum ColorTy {41    Yellow = int(HighlightColor::Address),42    Green = int(HighlightColor::String),43    DarkBlue = int(HighlightColor::Tag),44    Cyan = int(HighlightColor::Attribute),45    DarkPurple = int(HighlightColor::Enumerator),46    DarkRed = int(HighlightColor::Macro),47    BoldRed = int(HighlightColor::Error),48    BoldLightPurple = int(HighlightColor::Warning),49    BoldDarkGrey = int(HighlightColor::Note),50    BoldLightBlue = int(HighlightColor::Remark),51  };52 53  /// The banner printed at the beginning of an error report.54  static constexpr auto ErrorBanner = "OFFLOAD ERROR: ";55 56  /// Return the device id as string, or n/a if not available.57  static std::string getDeviceIdStr(GenericDeviceTy *Device) {58    return Device ? std::to_string(Device->getDeviceId()) : "n/a";59  }60 61  /// Return a nice name for an TargetAllocTy.62  static StringRef getAllocTyName(TargetAllocTy Kind) {63    switch (Kind) {64    case TARGET_ALLOC_DEFAULT:65    case TARGET_ALLOC_DEVICE:66      return "device memory";67    case TARGET_ALLOC_HOST:68      return "pinned host memory";69    case TARGET_ALLOC_SHARED:70      return "managed memory";71      break;72    }73    llvm_unreachable("Unknown target alloc kind");74  }75 76#pragma clang diagnostic push77#pragma clang diagnostic ignored "-Wgcc-compat"78#pragma clang diagnostic ignored "-Wformat-security"79  /// Print \p Format, instantiated with \p Args to stderr.80  /// TODO: Allow redirection into a file stream.81  template <typename... ArgsTy>82#ifdef __clang__ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=7795883  [[gnu::format(__printf__, 1, 2)]]84#endif85  static void print(const char *Format, ArgsTy &&...Args) {86    raw_fd_ostream OS(STDERR_FILENO, false);87    OS << llvm::format(Format, Args...);88  }89 90  /// Print \p Format, instantiated with \p Args to stderr, but colored.91  /// TODO: Allow redirection into a file stream.92  template <typename... ArgsTy>93#ifdef __clang__ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=7795894  [[gnu::format(__printf__, 2, 3)]]95#endif96  static void print(ColorTy Color, const char *Format, ArgsTy &&...Args) {97    raw_fd_ostream OS(STDERR_FILENO, false);98    WithColor(OS, HighlightColor(Color)) << llvm::format(Format, Args...);99  }100 101  /// Print \p Format, instantiated with \p Args to stderr, but colored and with102  /// a banner.103  /// TODO: Allow redirection into a file stream.104  template <typename... ArgsTy>105#ifdef __clang__ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77958106  [[gnu::format(__printf__, 1, 2)]]107#endif108  static void reportError(const char *Format, ArgsTy &&...Args) {109    print(BoldRed, "%s", ErrorBanner);110    print(BoldRed, Format, Args...);111    print("\n");112  }113#pragma clang diagnostic pop114 115  static void reportError(const char *Str) { reportError("%s", Str); }116  static void print(const char *Str) { print("%s", Str); }117  static void print(StringRef Str) { print("%s", Str.str().c_str()); }118  static void print(ColorTy Color, const char *Str) { print(Color, "%s", Str); }119  static void print(ColorTy Color, StringRef Str) {120    print(Color, "%s", Str.str().c_str());121  }122 123  /// Pretty print a stack trace.124  static void reportStackTrace(StringRef StackTrace) {125    if (StackTrace.empty())126      return;127 128    SmallVector<StringRef> Lines, Parts;129    StackTrace.split(Lines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);130    int Start = Lines.empty() || !Lines[0].contains("PrintStackTrace") ? 0 : 1;131    unsigned NumDigits =132        (int)(floor(log10(Lines.size() - Start - /*0*/ 1)) + 1);133    for (int I = Start, E = Lines.size(); I < E; ++I) {134      auto Line = Lines[I];135      Parts.clear();136      Line = Line.drop_while([](char C) { return std::isspace(C); });137      Line.split(Parts, " ", /*MaxSplit=*/2);138      if (Parts.size() != 3 || Parts[0].size() < 2 || Parts[0][0] != '#') {139        print("%s\n", Line.str().c_str());140        continue;141      }142      unsigned FrameIdx = std::stoi(Parts[0].drop_front(1).str());143      if (Start)144        FrameIdx -= 1;145      print(DarkPurple, "    %s", Parts[0].take_front().str().c_str());146      print(Green, "%*u", NumDigits, FrameIdx);147      print(BoldLightBlue, " %s", Parts[1].str().c_str());148      print(" %s\n", Parts[2].str().c_str());149    }150    print("\n");151  }152 153  /// Report information about an allocation associated with \p ATI.154  static void reportAllocationInfo(AllocationTraceInfoTy *ATI) {155    if (!ATI)156      return;157 158    if (!ATI->DeallocationTrace.empty()) {159      print(BoldLightPurple, "Last deallocation:\n");160      reportStackTrace(ATI->DeallocationTrace);161    }162 163    if (ATI->HostPtr)164      print(BoldLightPurple,165            "Last allocation of size %lu for host pointer %p -> device pointer "166            "%p:\n",167            ATI->Size, ATI->HostPtr, ATI->DevicePtr);168    else169      print(BoldLightPurple,170            "Last allocation of size %lu -> device pointer %p:\n", ATI->Size,171            ATI->DevicePtr);172    reportStackTrace(ATI->AllocationTrace);173    if (!ATI->LastAllocationInfo)174      return;175 176    unsigned I = 0;177    print(BoldLightPurple, "Prior allocations with the same base pointer:");178    while (ATI->LastAllocationInfo) {179      print("\n");180      ATI = ATI->LastAllocationInfo;181      print(BoldLightPurple, " #%u Prior deallocation of size %lu:\n", I,182            ATI->Size);183      reportStackTrace(ATI->DeallocationTrace);184      if (ATI->HostPtr)185        print(186            BoldLightPurple,187            " #%u Prior allocation for host pointer %p -> device pointer %p:\n",188            I, ATI->HostPtr, ATI->DevicePtr);189      else190        print(BoldLightPurple, " #%u Prior allocation -> device pointer %p:\n",191              I, ATI->DevicePtr);192      reportStackTrace(ATI->AllocationTrace);193      ++I;194    }195  }196 197  /// End the execution of the program.198  static void abortExecution() { abort(); }199 200public:201#define DEALLOCATION_ERROR(Format, ...)                                        \202  reportError(Format, __VA_ARGS__);                                            \203  reportStackTrace(StackTrace);                                                \204  reportAllocationInfo(ATI);                                                   \205  abortExecution();206 207  static void reportDeallocationOfNonAllocatedPtr(void *DevicePtr,208                                                  TargetAllocTy Kind,209                                                  AllocationTraceInfoTy *ATI,210                                                  std::string &StackTrace) {211    DEALLOCATION_ERROR("deallocation of non-allocated %s: %p",212                       getAllocTyName(Kind).data(), DevicePtr);213  }214 215  static void reportDeallocationOfDeallocatedPtr(void *DevicePtr,216                                                 TargetAllocTy Kind,217                                                 AllocationTraceInfoTy *ATI,218                                                 std::string &StackTrace) {219    DEALLOCATION_ERROR("double-free of %s: %p", getAllocTyName(Kind).data(),220                       DevicePtr);221  }222 223  static void reportDeallocationOfWrongPtrKind(void *DevicePtr,224                                               TargetAllocTy Kind,225                                               AllocationTraceInfoTy *ATI,226                                               std::string &StackTrace) {227    DEALLOCATION_ERROR("deallocation requires %s but allocation was %s: %p",228                       getAllocTyName(Kind).data(),229                       getAllocTyName(ATI->Kind).data(), DevicePtr);230#undef DEALLOCATION_ERROR231  }232 233  static void reportMemoryAccessError(GenericDeviceTy &Device, void *DevicePtr,234                                      std::string &ErrorStr, bool Abort) {235    reportError(ErrorStr.c_str());236 237    if (!Device.OMPX_TrackAllocationTraces) {238      print(Yellow, "Use '%s=true' to track device allocations\n",239            Device.OMPX_TrackAllocationTraces.getName().data());240      if (Abort)241        abortExecution();242      return;243    }244    uintptr_t Distance = false;245    auto *ATI =246        Device.getClosestAllocationTraceInfoForAddr(DevicePtr, Distance);247    if (!ATI) {248      print(Cyan,249            "No host-issued allocations; device pointer %p might be "250            "a global, stack, or shared location\n",251            DevicePtr);252      if (Abort)253        abortExecution();254      return;255    }256    if (!Distance) {257      print(Cyan, "Device pointer %p points into%s host-issued allocation:\n",258            DevicePtr, ATI->DeallocationTrace.empty() ? "" : " prior");259      reportAllocationInfo(ATI);260      if (Abort)261        abortExecution();262      return;263    }264 265    bool IsClose = Distance < (1L << 29L /*512MB=*/);266    print(Cyan,267          "Device pointer %p does not point into any (current or prior) "268          "host-issued allocation%s.\n",269          DevicePtr,270          IsClose ? "" : " (might be a global, stack, or shared location)");271    if (IsClose) {272      print(Cyan,273            "Closest host-issued allocation (distance %" PRIuPTR274            " byte%s; might be by page):\n",275            Distance, Distance > 1 ? "s" : "");276      reportAllocationInfo(ATI);277    }278    if (Abort)279      abortExecution();280  }281 282  /// Report that a kernel encountered a trap instruction.283  static void reportTrapInKernel(284      GenericDeviceTy &Device, KernelTraceInfoRecordTy &KTIR,285      std::function<bool(__tgt_async_info &)> AsyncInfoWrapperMatcher) {286    assert(AsyncInfoWrapperMatcher && "A matcher is required");287 288    uint32_t Idx = 0;289    for (uint32_t I = 0, E = KTIR.size(); I < E; ++I) {290      auto KTI = KTIR.getKernelTraceInfo(I);291      if (KTI.Kernel == nullptr)292        break;293      // Skip kernels issued in other queues.294      if (KTI.AsyncInfo && !(AsyncInfoWrapperMatcher(*KTI.AsyncInfo)))295        continue;296      Idx = I;297      break;298    }299 300    auto KTI = KTIR.getKernelTraceInfo(Idx);301    if (KTI.AsyncInfo && (AsyncInfoWrapperMatcher(*KTI.AsyncInfo))) {302      auto PrettyKernelName =303          llvm::omp::prettifyFunctionName(KTI.Kernel->getName());304      reportError("Kernel '%s'", PrettyKernelName.c_str());305    }306    reportError("execution interrupted by hardware trap instruction");307    if (KTI.AsyncInfo && (AsyncInfoWrapperMatcher(*KTI.AsyncInfo))) {308      if (!KTI.LaunchTrace.empty())309        reportStackTrace(KTI.LaunchTrace);310      else311        print(Yellow, "Use '%s=1' to show the stack trace of the kernel\n",312              Device.OMPX_TrackNumKernelLaunches.getName().data());313    }314    abort();315  }316 317  /// Report the kernel traces taken from \p KTIR, up to318  /// OFFLOAD_TRACK_NUM_KERNEL_LAUNCH_TRACES many.319  static void reportKernelTraces(GenericDeviceTy &Device,320                                 KernelTraceInfoRecordTy &KTIR) {321    uint32_t NumKTIs = 0;322    for (uint32_t I = 0, E = KTIR.size(); I < E; ++I) {323      auto KTI = KTIR.getKernelTraceInfo(I);324      if (KTI.Kernel == nullptr)325        break;326      ++NumKTIs;327    }328    if (NumKTIs == 0) {329      print(BoldRed, "No kernel launches known\n");330      return;331    }332 333    uint32_t TracesToShow =334        std::min(Device.OMPX_TrackNumKernelLaunches.get(), NumKTIs);335    if (TracesToShow == 0) {336      if (NumKTIs == 1)337        print(BoldLightPurple, "Display only launched kernel:\n");338      else339        print(BoldLightPurple, "Display last %u kernels launched:\n", NumKTIs);340    } else {341      if (NumKTIs == 1)342        print(BoldLightPurple, "Display kernel launch trace:\n");343      else344        print(BoldLightPurple,345              "Display %u of the %u last kernel launch traces:\n", TracesToShow,346              NumKTIs);347    }348 349    for (uint32_t Idx = 0, I = 0; I < NumKTIs; ++Idx) {350      auto KTI = KTIR.getKernelTraceInfo(Idx);351      auto PrettyKernelName =352          llvm::omp::prettifyFunctionName(KTI.Kernel->getName());353      if (NumKTIs == 1)354        print(BoldLightPurple, "Kernel '%s'\n", PrettyKernelName.c_str());355      else356        print(BoldLightPurple, "Kernel %d: '%s'\n", I,357              PrettyKernelName.c_str());358      reportStackTrace(KTI.LaunchTrace);359      ++I;360    }361 362    if (NumKTIs != 1) {363      print(Yellow,364            "Use '%s=<num>' to adjust the number of shown stack traces (%u "365            "now, up to %zu)\n",366            Device.OMPX_TrackNumKernelLaunches.getName().data(),367            Device.OMPX_TrackNumKernelLaunches.get(), KTIR.size());368    }369    // TODO: Let users know how to serialize kernels370  }371};372 373} // namespace plugin374} // namespace target375} // namespace omp376} // namespace llvm377 378#endif // OFFLOAD_PLUGINS_NEXTGEN_COMMON_ERROR_REPORTING_H379