1c95abe94SJohannes Doerfert //===- ErrorReporting.h - Helper to provide nice error messages ----- c++ -===// 2c95abe94SJohannes Doerfert // 3c95abe94SJohannes Doerfert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c95abe94SJohannes Doerfert // See https://llvm.org/LICENSE.txt for license information. 5c95abe94SJohannes Doerfert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c95abe94SJohannes Doerfert // 7c95abe94SJohannes Doerfert //===----------------------------------------------------------------------===// 8c95abe94SJohannes Doerfert // 9c95abe94SJohannes Doerfert //===----------------------------------------------------------------------===// 10c95abe94SJohannes Doerfert 11c95abe94SJohannes Doerfert #ifndef OFFLOAD_PLUGINS_NEXTGEN_COMMON_ERROR_REPORTING_H 12c95abe94SJohannes Doerfert #define OFFLOAD_PLUGINS_NEXTGEN_COMMON_ERROR_REPORTING_H 13c95abe94SJohannes Doerfert 14c95abe94SJohannes Doerfert #include "PluginInterface.h" 15c95abe94SJohannes Doerfert #include "Shared/EnvironmentVar.h" 16c95abe94SJohannes Doerfert 179a101322SJohannes Doerfert #include "llvm/ADT/STLExtras.h" 18c95abe94SJohannes Doerfert #include "llvm/ADT/SmallString.h" 19c95abe94SJohannes Doerfert #include "llvm/ADT/StringRef.h" 20f3bfc563SJohannes Doerfert #include "llvm/Frontend/OpenMP/OMP.h" 21c95abe94SJohannes Doerfert #include "llvm/Support/ErrorHandling.h" 22c95abe94SJohannes Doerfert #include "llvm/Support/WithColor.h" 23c95abe94SJohannes Doerfert #include "llvm/Support/raw_ostream.h" 24c95abe94SJohannes Doerfert 25c95abe94SJohannes Doerfert #include <cstdint> 26c95abe94SJohannes Doerfert #include <cstdio> 27c95abe94SJohannes Doerfert #include <cstdlib> 28c95abe94SJohannes Doerfert #include <functional> 29c95abe94SJohannes Doerfert #include <optional> 30c95abe94SJohannes Doerfert #include <string> 31c95abe94SJohannes Doerfert #include <unistd.h> 32c95abe94SJohannes Doerfert 33c95abe94SJohannes Doerfert namespace llvm { 34c95abe94SJohannes Doerfert namespace omp { 35c95abe94SJohannes Doerfert namespace target { 36c95abe94SJohannes Doerfert namespace plugin { 37c95abe94SJohannes Doerfert 38c95abe94SJohannes Doerfert class ErrorReporter { 39c95abe94SJohannes Doerfert 40c95abe94SJohannes Doerfert enum ColorTy { 41c95abe94SJohannes Doerfert Yellow = int(HighlightColor::Address), 42c95abe94SJohannes Doerfert Green = int(HighlightColor::String), 43c95abe94SJohannes Doerfert DarkBlue = int(HighlightColor::Tag), 44c95abe94SJohannes Doerfert Cyan = int(HighlightColor::Attribute), 45c95abe94SJohannes Doerfert DarkPurple = int(HighlightColor::Enumerator), 46c95abe94SJohannes Doerfert DarkRed = int(HighlightColor::Macro), 47c95abe94SJohannes Doerfert BoldRed = int(HighlightColor::Error), 48c95abe94SJohannes Doerfert BoldLightPurple = int(HighlightColor::Warning), 49c95abe94SJohannes Doerfert BoldDarkGrey = int(HighlightColor::Note), 50c95abe94SJohannes Doerfert BoldLightBlue = int(HighlightColor::Remark), 51c95abe94SJohannes Doerfert }; 52c95abe94SJohannes Doerfert 53c95abe94SJohannes Doerfert /// The banner printed at the beginning of an error report. 54c95abe94SJohannes Doerfert static constexpr auto ErrorBanner = "OFFLOAD ERROR: "; 55c95abe94SJohannes Doerfert 56c95abe94SJohannes Doerfert /// Return the device id as string, or n/a if not available. 57c95abe94SJohannes Doerfert static std::string getDeviceIdStr(GenericDeviceTy *Device) { 58c95abe94SJohannes Doerfert return Device ? std::to_string(Device->getDeviceId()) : "n/a"; 59c95abe94SJohannes Doerfert } 60c95abe94SJohannes Doerfert 61c95abe94SJohannes Doerfert /// Return a nice name for an TargetAllocTy. 62c95abe94SJohannes Doerfert static StringRef getAllocTyName(TargetAllocTy Kind) { 63c95abe94SJohannes Doerfert switch (Kind) { 64c95abe94SJohannes Doerfert case TARGET_ALLOC_DEVICE_NON_BLOCKING: 65c95abe94SJohannes Doerfert case TARGET_ALLOC_DEFAULT: 66c95abe94SJohannes Doerfert case TARGET_ALLOC_DEVICE: 67c95abe94SJohannes Doerfert return "device memory"; 68c95abe94SJohannes Doerfert case TARGET_ALLOC_HOST: 69c95abe94SJohannes Doerfert return "pinned host memory"; 70c95abe94SJohannes Doerfert case TARGET_ALLOC_SHARED: 71c95abe94SJohannes Doerfert return "managed memory"; 72c95abe94SJohannes Doerfert break; 73c95abe94SJohannes Doerfert } 74c95abe94SJohannes Doerfert llvm_unreachable("Unknown target alloc kind"); 75c95abe94SJohannes Doerfert } 76c95abe94SJohannes Doerfert 77c95abe94SJohannes Doerfert #pragma clang diagnostic push 78c95abe94SJohannes Doerfert #pragma clang diagnostic ignored "-Wgcc-compat" 79c95abe94SJohannes Doerfert #pragma clang diagnostic ignored "-Wformat-security" 80c95abe94SJohannes Doerfert /// Print \p Format, instantiated with \p Args to stderr. 81c95abe94SJohannes Doerfert /// TODO: Allow redirection into a file stream. 82c95abe94SJohannes Doerfert template <typename... ArgsTy> 83c95abe94SJohannes Doerfert [[gnu::format(__printf__, 1, 2)]] static void print(const char *Format, 84c95abe94SJohannes Doerfert ArgsTy &&...Args) { 85c95abe94SJohannes Doerfert raw_fd_ostream OS(STDERR_FILENO, false); 86c95abe94SJohannes Doerfert OS << llvm::format(Format, Args...); 87c95abe94SJohannes Doerfert } 88c95abe94SJohannes Doerfert 89c95abe94SJohannes Doerfert /// Print \p Format, instantiated with \p Args to stderr, but colored. 90c95abe94SJohannes Doerfert /// TODO: Allow redirection into a file stream. 91c95abe94SJohannes Doerfert template <typename... ArgsTy> 92c95abe94SJohannes Doerfert [[gnu::format(__printf__, 2, 3)]] static void 93c95abe94SJohannes Doerfert print(ColorTy Color, const char *Format, ArgsTy &&...Args) { 94c95abe94SJohannes Doerfert raw_fd_ostream OS(STDERR_FILENO, false); 95c95abe94SJohannes Doerfert WithColor(OS, HighlightColor(Color)) << llvm::format(Format, Args...); 96c95abe94SJohannes Doerfert } 97c95abe94SJohannes Doerfert 98c95abe94SJohannes Doerfert /// Print \p Format, instantiated with \p Args to stderr, but colored and with 99c95abe94SJohannes Doerfert /// a banner. 100c95abe94SJohannes Doerfert /// TODO: Allow redirection into a file stream. 101c95abe94SJohannes Doerfert template <typename... ArgsTy> 102c95abe94SJohannes Doerfert [[gnu::format(__printf__, 1, 2)]] static void reportError(const char *Format, 103c95abe94SJohannes Doerfert ArgsTy &&...Args) { 104c95abe94SJohannes Doerfert print(BoldRed, "%s", ErrorBanner); 105c95abe94SJohannes Doerfert print(BoldRed, Format, Args...); 106c95abe94SJohannes Doerfert print("\n"); 107c95abe94SJohannes Doerfert } 108c95abe94SJohannes Doerfert #pragma clang diagnostic pop 109c95abe94SJohannes Doerfert 110c95abe94SJohannes Doerfert static void reportError(const char *Str) { reportError("%s", Str); } 111c95abe94SJohannes Doerfert static void print(const char *Str) { print("%s", Str); } 112c95abe94SJohannes Doerfert static void print(StringRef Str) { print("%s", Str.str().c_str()); } 113c95abe94SJohannes Doerfert static void print(ColorTy Color, const char *Str) { print(Color, "%s", Str); } 114c95abe94SJohannes Doerfert static void print(ColorTy Color, StringRef Str) { 115c95abe94SJohannes Doerfert print(Color, "%s", Str.str().c_str()); 116c95abe94SJohannes Doerfert } 117c95abe94SJohannes Doerfert 118c95abe94SJohannes Doerfert /// Pretty print a stack trace. 119c95abe94SJohannes Doerfert static void reportStackTrace(StringRef StackTrace) { 120c95abe94SJohannes Doerfert if (StackTrace.empty()) 121c95abe94SJohannes Doerfert return; 122c95abe94SJohannes Doerfert 123c95abe94SJohannes Doerfert SmallVector<StringRef> Lines, Parts; 124c95abe94SJohannes Doerfert StackTrace.split(Lines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); 125c95abe94SJohannes Doerfert int Start = Lines.empty() || !Lines[0].contains("PrintStackTrace") ? 0 : 1; 126c95abe94SJohannes Doerfert unsigned NumDigits = 127c95abe94SJohannes Doerfert (int)(floor(log10(Lines.size() - Start - /*0*/ 1)) + 1); 128c95abe94SJohannes Doerfert for (int I = Start, E = Lines.size(); I < E; ++I) { 129c95abe94SJohannes Doerfert auto Line = Lines[I]; 130c95abe94SJohannes Doerfert Parts.clear(); 131c95abe94SJohannes Doerfert Line = Line.drop_while([](char C) { return std::isspace(C); }); 132c95abe94SJohannes Doerfert Line.split(Parts, " ", /*MaxSplit=*/2); 133c95abe94SJohannes Doerfert if (Parts.size() != 3 || Parts[0].size() < 2 || Parts[0][0] != '#') { 134c95abe94SJohannes Doerfert print("%s\n", Line.str().c_str()); 135c95abe94SJohannes Doerfert continue; 136c95abe94SJohannes Doerfert } 137c95abe94SJohannes Doerfert unsigned FrameIdx = std::stoi(Parts[0].drop_front(1).str()); 138c95abe94SJohannes Doerfert if (Start) 139c95abe94SJohannes Doerfert FrameIdx -= 1; 140c95abe94SJohannes Doerfert print(DarkPurple, " %s", Parts[0].take_front().str().c_str()); 141c95abe94SJohannes Doerfert print(Green, "%*u", NumDigits, FrameIdx); 142c95abe94SJohannes Doerfert print(BoldLightBlue, " %s", Parts[1].str().c_str()); 143c95abe94SJohannes Doerfert print(" %s\n", Parts[2].str().c_str()); 144c95abe94SJohannes Doerfert } 145c95abe94SJohannes Doerfert print("\n"); 146c95abe94SJohannes Doerfert } 147c95abe94SJohannes Doerfert 148c95abe94SJohannes Doerfert /// Report information about an allocation associated with \p ATI. 149c95abe94SJohannes Doerfert static void reportAllocationInfo(AllocationTraceInfoTy *ATI) { 150c95abe94SJohannes Doerfert if (!ATI) 151c95abe94SJohannes Doerfert return; 152c95abe94SJohannes Doerfert 153c95abe94SJohannes Doerfert if (!ATI->DeallocationTrace.empty()) { 154c95abe94SJohannes Doerfert print(BoldLightPurple, "Last deallocation:\n"); 155c95abe94SJohannes Doerfert reportStackTrace(ATI->DeallocationTrace); 156c95abe94SJohannes Doerfert } 157c95abe94SJohannes Doerfert 158c95abe94SJohannes Doerfert if (ATI->HostPtr) 159c95abe94SJohannes Doerfert print(BoldLightPurple, 160*3b761159SJohannes Doerfert "Last allocation of size %lu for host pointer %p -> device pointer " 161*3b761159SJohannes Doerfert "%p:\n", 162*3b761159SJohannes Doerfert ATI->Size, ATI->HostPtr, ATI->DevicePtr); 163c95abe94SJohannes Doerfert else 164*3b761159SJohannes Doerfert print(BoldLightPurple, 165*3b761159SJohannes Doerfert "Last allocation of size %lu -> device pointer %p:\n", ATI->Size, 166*3b761159SJohannes Doerfert ATI->DevicePtr); 167c95abe94SJohannes Doerfert reportStackTrace(ATI->AllocationTrace); 168c95abe94SJohannes Doerfert if (!ATI->LastAllocationInfo) 169c95abe94SJohannes Doerfert return; 170c95abe94SJohannes Doerfert 171c95abe94SJohannes Doerfert unsigned I = 0; 172c95abe94SJohannes Doerfert print(BoldLightPurple, "Prior allocations with the same base pointer:"); 173c95abe94SJohannes Doerfert while (ATI->LastAllocationInfo) { 174c95abe94SJohannes Doerfert print("\n"); 175c95abe94SJohannes Doerfert ATI = ATI->LastAllocationInfo; 176c95abe94SJohannes Doerfert print(BoldLightPurple, " #%u Prior deallocation of size %lu:\n", I, 177c95abe94SJohannes Doerfert ATI->Size); 178c95abe94SJohannes Doerfert reportStackTrace(ATI->DeallocationTrace); 179c95abe94SJohannes Doerfert if (ATI->HostPtr) 180*3b761159SJohannes Doerfert print( 181*3b761159SJohannes Doerfert BoldLightPurple, 182*3b761159SJohannes Doerfert " #%u Prior allocation for host pointer %p -> device pointer %p:\n", 183*3b761159SJohannes Doerfert I, ATI->HostPtr, ATI->DevicePtr); 184c95abe94SJohannes Doerfert else 185*3b761159SJohannes Doerfert print(BoldLightPurple, " #%u Prior allocation -> device pointer %p:\n", 186*3b761159SJohannes Doerfert I, ATI->DevicePtr); 187c95abe94SJohannes Doerfert reportStackTrace(ATI->AllocationTrace); 188c95abe94SJohannes Doerfert ++I; 189c95abe94SJohannes Doerfert } 190c95abe94SJohannes Doerfert } 191c95abe94SJohannes Doerfert 192c95abe94SJohannes Doerfert /// End the execution of the program. 193c95abe94SJohannes Doerfert static void abortExecution() { abort(); } 194c95abe94SJohannes Doerfert 195c95abe94SJohannes Doerfert public: 196c95abe94SJohannes Doerfert #define DEALLOCATION_ERROR(Format, ...) \ 197c95abe94SJohannes Doerfert reportError(Format, __VA_ARGS__); \ 198c95abe94SJohannes Doerfert reportStackTrace(StackTrace); \ 199c95abe94SJohannes Doerfert reportAllocationInfo(ATI); \ 200c95abe94SJohannes Doerfert abortExecution(); 201c95abe94SJohannes Doerfert 202c95abe94SJohannes Doerfert static void reportDeallocationOfNonAllocatedPtr(void *DevicePtr, 203c95abe94SJohannes Doerfert TargetAllocTy Kind, 204c95abe94SJohannes Doerfert AllocationTraceInfoTy *ATI, 205c95abe94SJohannes Doerfert std::string &StackTrace) { 206c95abe94SJohannes Doerfert DEALLOCATION_ERROR("deallocation of non-allocated %s: %p", 207c95abe94SJohannes Doerfert getAllocTyName(Kind).data(), DevicePtr); 208c95abe94SJohannes Doerfert } 209c95abe94SJohannes Doerfert 210c95abe94SJohannes Doerfert static void reportDeallocationOfDeallocatedPtr(void *DevicePtr, 211c95abe94SJohannes Doerfert TargetAllocTy Kind, 212c95abe94SJohannes Doerfert AllocationTraceInfoTy *ATI, 213c95abe94SJohannes Doerfert std::string &StackTrace) { 214c95abe94SJohannes Doerfert DEALLOCATION_ERROR("double-free of %s: %p", getAllocTyName(Kind).data(), 215c95abe94SJohannes Doerfert DevicePtr); 216c95abe94SJohannes Doerfert } 217c95abe94SJohannes Doerfert 218c95abe94SJohannes Doerfert static void reportDeallocationOfWrongPtrKind(void *DevicePtr, 219c95abe94SJohannes Doerfert TargetAllocTy Kind, 220c95abe94SJohannes Doerfert AllocationTraceInfoTy *ATI, 221c95abe94SJohannes Doerfert std::string &StackTrace) { 222c95abe94SJohannes Doerfert DEALLOCATION_ERROR("deallocation requires %s but allocation was %s: %p", 223c95abe94SJohannes Doerfert getAllocTyName(Kind).data(), 224c95abe94SJohannes Doerfert getAllocTyName(ATI->Kind).data(), DevicePtr); 225c95abe94SJohannes Doerfert #undef DEALLOCATION_ERROR 226c95abe94SJohannes Doerfert } 2279a101322SJohannes Doerfert 228*3b761159SJohannes Doerfert static void reportMemoryAccessError(GenericDeviceTy &Device, void *DevicePtr, 229*3b761159SJohannes Doerfert std::string &ErrorStr, bool Abort) { 230*3b761159SJohannes Doerfert reportError(ErrorStr.c_str()); 231*3b761159SJohannes Doerfert 232*3b761159SJohannes Doerfert if (!Device.OMPX_TrackAllocationTraces) { 233*3b761159SJohannes Doerfert print(Yellow, "Use '%s=true' to track device allocations\n", 234*3b761159SJohannes Doerfert Device.OMPX_TrackAllocationTraces.getName().data()); 235*3b761159SJohannes Doerfert if (Abort) 236*3b761159SJohannes Doerfert abortExecution(); 237*3b761159SJohannes Doerfert return; 238*3b761159SJohannes Doerfert } 239*3b761159SJohannes Doerfert uintptr_t Distance = false; 240*3b761159SJohannes Doerfert auto *ATI = 241*3b761159SJohannes Doerfert Device.getClosestAllocationTraceInfoForAddr(DevicePtr, Distance); 242*3b761159SJohannes Doerfert if (!ATI) { 243*3b761159SJohannes Doerfert print(Cyan, 244*3b761159SJohannes Doerfert "No host-issued allocations; device pointer %p might be " 245*3b761159SJohannes Doerfert "a global, stack, or shared location\n", 246*3b761159SJohannes Doerfert DevicePtr); 247*3b761159SJohannes Doerfert if (Abort) 248*3b761159SJohannes Doerfert abortExecution(); 249*3b761159SJohannes Doerfert return; 250*3b761159SJohannes Doerfert } 251*3b761159SJohannes Doerfert if (!Distance) { 252*3b761159SJohannes Doerfert print(Cyan, "Device pointer %p points into%s host-issued allocation:\n", 253*3b761159SJohannes Doerfert DevicePtr, ATI->DeallocationTrace.empty() ? "" : " prior"); 254*3b761159SJohannes Doerfert reportAllocationInfo(ATI); 255*3b761159SJohannes Doerfert if (Abort) 256*3b761159SJohannes Doerfert abortExecution(); 257*3b761159SJohannes Doerfert return; 258*3b761159SJohannes Doerfert } 259*3b761159SJohannes Doerfert 260*3b761159SJohannes Doerfert bool IsClose = Distance < (1L << 29L /*512MB=*/); 261*3b761159SJohannes Doerfert print(Cyan, 262*3b761159SJohannes Doerfert "Device pointer %p does not point into any (current or prior) " 263*3b761159SJohannes Doerfert "host-issued allocation%s.\n", 264*3b761159SJohannes Doerfert DevicePtr, 265*3b761159SJohannes Doerfert IsClose ? "" : " (might be a global, stack, or shared location)"); 266*3b761159SJohannes Doerfert if (IsClose) { 267*3b761159SJohannes Doerfert print(Cyan, 268*3b761159SJohannes Doerfert "Closest host-issued allocation (distance %" PRIuPTR 269*3b761159SJohannes Doerfert " byte%s; might be by page):\n", 270*3b761159SJohannes Doerfert Distance, Distance > 1 ? "s" : ""); 271*3b761159SJohannes Doerfert reportAllocationInfo(ATI); 272*3b761159SJohannes Doerfert } 273*3b761159SJohannes Doerfert if (Abort) 274*3b761159SJohannes Doerfert abortExecution(); 275*3b761159SJohannes Doerfert } 276*3b761159SJohannes Doerfert 2779a101322SJohannes Doerfert /// Report that a kernel encountered a trap instruction. 2789a101322SJohannes Doerfert static void reportTrapInKernel( 2799a101322SJohannes Doerfert GenericDeviceTy &Device, KernelTraceInfoRecordTy &KTIR, 2809a101322SJohannes Doerfert std::function<bool(__tgt_async_info &)> AsyncInfoWrapperMatcher) { 2819a101322SJohannes Doerfert assert(AsyncInfoWrapperMatcher && "A matcher is required"); 2829a101322SJohannes Doerfert 2839a101322SJohannes Doerfert uint32_t Idx = 0; 2849a101322SJohannes Doerfert for (uint32_t I = 0, E = KTIR.size(); I < E; ++I) { 2859a101322SJohannes Doerfert auto KTI = KTIR.getKernelTraceInfo(I); 2869a101322SJohannes Doerfert if (KTI.Kernel == nullptr) 2879a101322SJohannes Doerfert break; 2889a101322SJohannes Doerfert // Skip kernels issued in other queues. 2899a101322SJohannes Doerfert if (KTI.AsyncInfo && !(AsyncInfoWrapperMatcher(*KTI.AsyncInfo))) 2909a101322SJohannes Doerfert continue; 2919a101322SJohannes Doerfert Idx = I; 2929a101322SJohannes Doerfert break; 2939a101322SJohannes Doerfert } 2949a101322SJohannes Doerfert 2959a101322SJohannes Doerfert auto KTI = KTIR.getKernelTraceInfo(Idx); 296f3bfc563SJohannes Doerfert if (KTI.AsyncInfo && (AsyncInfoWrapperMatcher(*KTI.AsyncInfo))) { 297f3bfc563SJohannes Doerfert auto PrettyKernelName = 298f3bfc563SJohannes Doerfert llvm::omp::prettifyFunctionName(KTI.Kernel->getName()); 299f3bfc563SJohannes Doerfert reportError("Kernel '%s'", PrettyKernelName.c_str()); 300f3bfc563SJohannes Doerfert } 3019a101322SJohannes Doerfert reportError("execution interrupted by hardware trap instruction"); 3029a101322SJohannes Doerfert if (KTI.AsyncInfo && (AsyncInfoWrapperMatcher(*KTI.AsyncInfo))) { 3039a101322SJohannes Doerfert if (!KTI.LaunchTrace.empty()) 3049a101322SJohannes Doerfert reportStackTrace(KTI.LaunchTrace); 3059a101322SJohannes Doerfert else 3069a101322SJohannes Doerfert print(Yellow, "Use '%s=1' to show the stack trace of the kernel\n", 3079a101322SJohannes Doerfert Device.OMPX_TrackNumKernelLaunches.getName().data()); 3089a101322SJohannes Doerfert } 3099a101322SJohannes Doerfert abort(); 3109a101322SJohannes Doerfert } 3119a101322SJohannes Doerfert 3129a101322SJohannes Doerfert /// Report the kernel traces taken from \p KTIR, up to 3139a101322SJohannes Doerfert /// OFFLOAD_TRACK_NUM_KERNEL_LAUNCH_TRACES many. 3149a101322SJohannes Doerfert static void reportKernelTraces(GenericDeviceTy &Device, 3159a101322SJohannes Doerfert KernelTraceInfoRecordTy &KTIR) { 3169a101322SJohannes Doerfert uint32_t NumKTIs = 0; 3179a101322SJohannes Doerfert for (uint32_t I = 0, E = KTIR.size(); I < E; ++I) { 3189a101322SJohannes Doerfert auto KTI = KTIR.getKernelTraceInfo(I); 3199a101322SJohannes Doerfert if (KTI.Kernel == nullptr) 3209a101322SJohannes Doerfert break; 3219a101322SJohannes Doerfert ++NumKTIs; 3229a101322SJohannes Doerfert } 3239a101322SJohannes Doerfert if (NumKTIs == 0) { 3249a101322SJohannes Doerfert print(BoldRed, "No kernel launches known\n"); 3259a101322SJohannes Doerfert return; 3269a101322SJohannes Doerfert } 3279a101322SJohannes Doerfert 3289a101322SJohannes Doerfert uint32_t TracesToShow = 3299a101322SJohannes Doerfert std::min(Device.OMPX_TrackNumKernelLaunches.get(), NumKTIs); 3309a101322SJohannes Doerfert if (TracesToShow == 0) { 3319a101322SJohannes Doerfert if (NumKTIs == 1) 3329a101322SJohannes Doerfert print(BoldLightPurple, "Display only launched kernel:\n"); 3339a101322SJohannes Doerfert else 3349a101322SJohannes Doerfert print(BoldLightPurple, "Display last %u kernels launched:\n", NumKTIs); 3359a101322SJohannes Doerfert } else { 3369a101322SJohannes Doerfert if (NumKTIs == 1) 3379a101322SJohannes Doerfert print(BoldLightPurple, "Display kernel launch trace:\n"); 3389a101322SJohannes Doerfert else 3399a101322SJohannes Doerfert print(BoldLightPurple, 3409a101322SJohannes Doerfert "Display %u of the %u last kernel launch traces:\n", TracesToShow, 3419a101322SJohannes Doerfert NumKTIs); 3429a101322SJohannes Doerfert } 3439a101322SJohannes Doerfert 3449a101322SJohannes Doerfert for (uint32_t Idx = 0, I = 0; I < NumKTIs; ++Idx) { 3459a101322SJohannes Doerfert auto KTI = KTIR.getKernelTraceInfo(Idx); 346f3bfc563SJohannes Doerfert auto PrettyKernelName = 347f3bfc563SJohannes Doerfert llvm::omp::prettifyFunctionName(KTI.Kernel->getName()); 3489a101322SJohannes Doerfert if (NumKTIs == 1) 349f3bfc563SJohannes Doerfert print(BoldLightPurple, "Kernel '%s'\n", PrettyKernelName.c_str()); 3509a101322SJohannes Doerfert else 351f3bfc563SJohannes Doerfert print(BoldLightPurple, "Kernel %d: '%s'\n", I, 352f3bfc563SJohannes Doerfert PrettyKernelName.c_str()); 3539a101322SJohannes Doerfert reportStackTrace(KTI.LaunchTrace); 3549a101322SJohannes Doerfert ++I; 3559a101322SJohannes Doerfert } 3569a101322SJohannes Doerfert 3579a101322SJohannes Doerfert if (NumKTIs != 1) { 3589a101322SJohannes Doerfert print(Yellow, 3599a101322SJohannes Doerfert "Use '%s=<num>' to adjust the number of shown stack traces (%u " 3609a101322SJohannes Doerfert "now, up to %zu)\n", 3619a101322SJohannes Doerfert Device.OMPX_TrackNumKernelLaunches.getName().data(), 3629a101322SJohannes Doerfert Device.OMPX_TrackNumKernelLaunches.get(), KTIR.size()); 3639a101322SJohannes Doerfert } 3649a101322SJohannes Doerfert // TODO: Let users know how to serialize kernels 3659a101322SJohannes Doerfert } 366c95abe94SJohannes Doerfert }; 367c95abe94SJohannes Doerfert 368c95abe94SJohannes Doerfert } // namespace plugin 369c95abe94SJohannes Doerfert } // namespace target 370c95abe94SJohannes Doerfert } // namespace omp 371c95abe94SJohannes Doerfert } // namespace llvm 372c95abe94SJohannes Doerfert 373c95abe94SJohannes Doerfert #endif // OFFLOAD_PLUGINS_NEXTGEN_COMMON_ERROR_REPORTING_H 374