diff --git a/openmp/libomptarget/include/Ident.h b/openmp/libomptarget/include/Ident.h new file mode 100644 --- /dev/null +++ b/openmp/libomptarget/include/Ident.h @@ -0,0 +1,69 @@ +//===-------- Ident.h - Target independent OpenMP target RTL -- C++ -----*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Methods used to describe source information in target regions +// +//===----------------------------------------------------------------------===// + +#ifndef _IDENT_H_ +#define _IDENT_H_ + +#ifdef _WIN32 +static const bool OS_WINDOWS = true; +#else +static const bool OS_WINDOWS = false; +#endif + +/// Type alias for source location information for variable mappings with +/// layout ;name;filename;row;col;; +using name_t = void; + +/// Struct to hold source individual location information +struct SourceInfo { + std::string name; + std::string filename; + int32_t line; + int32_t column; +}; + +/// Get a SourceInfo struct from a mapping name +static inline SourceInfo getSourceInfo(const name_t *name) { + if (!name) + return SourceInfo{"unknown", "unknown", 0, 0}; + + const std::string name_str((const char *)name); + auto getSubstring = [&name_str](const int n) { + std::size_t begin = name_str.find(';'); + std::size_t end = name_str.find(';', begin + 1); + for (int i = 0; i < n; i++) { + begin = end; + end = name_str.find(';', begin + 1); + } + return name_str.substr(begin + 1, end - begin - 1); + }; + auto removePath = [](const std::string &path) { + std::size_t pos = (OS_WINDOWS) ? path.rfind('\\') : path.rfind('/'); + return path.substr(pos + 1); + }; + + return SourceInfo{getSubstring(0), removePath(getSubstring(1)), + std::stoi(getSubstring(2)), std::stoi(getSubstring(3))}; +} + +/// Standalone function for getting the variable name of a mapping +static inline std::string getName(const name_t *name) { + if (!name) + return "unknown"; + + const std::string name_str((const char *)name); + std::size_t begin = name_str.find(';'); + std::size_t end = name_str.find(';', begin + 1); + return name_str.substr(begin + 1, end - begin - 1); +} + +#endif diff --git a/openmp/libomptarget/include/omptarget.h b/openmp/libomptarget/include/omptarget.h --- a/openmp/libomptarget/include/omptarget.h +++ b/openmp/libomptarget/include/omptarget.h @@ -17,6 +17,8 @@ #include #include +#include + #define OFFLOAD_SUCCESS (0) #define OFFLOAD_FAIL (~0) diff --git a/openmp/libomptarget/src/device.h b/openmp/libomptarget/src/device.h --- a/openmp/libomptarget/src/device.h +++ b/openmp/libomptarget/src/device.h @@ -34,9 +34,11 @@ uintptr_t HstPtrBase; // host info. uintptr_t HstPtrBegin; uintptr_t HstPtrEnd; // non-inclusive. + void *HstPtrName; // Source name of mapped variable uintptr_t TgtPtrBegin; // target info. + private: /// use mutable to allow modification via std::set iterator which is const. mutable uint64_t RefCount; @@ -44,9 +46,9 @@ public: HostDataToTargetTy(uintptr_t BP, uintptr_t B, uintptr_t E, uintptr_t TB, - bool IsINF = false) + void *Name = nullptr, bool IsINF = false) : HstPtrBase(BP), HstPtrBegin(B), HstPtrEnd(E), - TgtPtrBegin(TB), RefCount(IsINF ? INFRefCount : 1) {} + HstPtrName(Name), TgtPtrBegin(TB), RefCount(IsINF ? INFRefCount : 1) {} uint64_t getRefCount() const { return RefCount; @@ -163,7 +165,7 @@ uint64_t getMapEntryRefCnt(void *HstPtrBegin); LookupResult lookupMapping(void *HstPtrBegin, int64_t Size); void *getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase, int64_t Size, - bool &IsNew, bool &IsHostPtr, bool IsImplicit, + void *HstPtrName, bool &IsNew, bool &IsHostPtr, bool IsImplicit, bool UpdateRefCount, bool HasCloseModifier, bool HasPresentModifier); void *getTgtPtrBegin(void *HstPtrBegin, int64_t Size); diff --git a/openmp/libomptarget/src/device.cpp b/openmp/libomptarget/src/device.cpp --- a/openmp/libomptarget/src/device.cpp +++ b/openmp/libomptarget/src/device.cpp @@ -84,6 +84,7 @@ (uintptr_t) HstPtrBegin /*HstPtrBegin*/, (uintptr_t) HstPtrBegin + Size /*HstPtrEnd*/, (uintptr_t) TgtPtrBegin /*TgtPtrBegin*/, + nullptr, true /*IsRefCountINF*/); DP("Creating new map entry: HstBase=" DPxMOD ", HstBegin=" DPxMOD ", HstEnd=" @@ -197,9 +198,9 @@ // If NULL is returned, then either data allocation failed or the user tried // to do an illegal mapping. void *DeviceTy::getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase, - int64_t Size, bool &IsNew, bool &IsHostPtr, - bool IsImplicit, bool UpdateRefCount, - bool HasCloseModifier, + int64_t Size, void *HstPtrName, bool &IsNew, + bool &IsHostPtr, bool IsImplicit, + bool UpdateRefCount, bool HasCloseModifier, bool HasPresentModifier) { void *rc = NULL; IsHostPtr = false; @@ -223,10 +224,11 @@ INFO(DeviceID, "Mapping exists%s with HstPtrBegin=" DPxMOD ", TgtPtrBegin=" DPxMOD ", " - "Size=%" PRId64 ",%s RefCount=%s\n", + "Size=%" PRId64 ",%s RefCount=%s, Name=%s\n", (IsImplicit ? " (implicit)" : ""), DPxPTR(HstPtrBegin), DPxPTR(tp), Size, (UpdateRefCount ? " updated" : ""), - HT.isRefCountInf() ? "INF" : std::to_string(HT.getRefCount()).c_str()); + HT.isRefCountInf() ? "INF" : std::to_string(HT.getRefCount()).c_str(), + (HstPtrName) ? getName(HstPtrName).c_str() : "(null)"); rc = (void *)tp; } else if ((lr.Flags.ExtendsBefore || lr.Flags.ExtendsAfter) && !IsImplicit) { // Explicit extension of mapped data - not allowed. @@ -271,7 +273,7 @@ DPxPTR((uintptr_t)HstPtrBegin + Size), DPxPTR(tp)); HostDataToTargetMap.emplace( HostDataToTargetTy((uintptr_t)HstPtrBase, (uintptr_t)HstPtrBegin, - (uintptr_t)HstPtrBegin + Size, tp)); + (uintptr_t)HstPtrBegin + Size, tp, HstPtrName)); rc = (void *)tp; } diff --git a/openmp/libomptarget/src/interface.cpp b/openmp/libomptarget/src/interface.cpp --- a/openmp/libomptarget/src/interface.cpp +++ b/openmp/libomptarget/src/interface.cpp @@ -138,14 +138,14 @@ #ifdef OMPTARGET_DEBUG for (int i = 0; i < arg_num; ++i) { DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64 - ", Type=0x%" PRIx64 "%s\n", + ", Type=0x%" PRIx64 ", Name=%s\n", i, DPxPTR(args_base[i]), DPxPTR(args[i]), arg_sizes[i], arg_types[i], - arg_names[i]); + (arg_names) ? getName(arg_names[i]).c_str() : "(null)"); } #endif int rc = targetDataBegin(Device, arg_num, args_base, args, arg_sizes, - arg_types, arg_mappers, nullptr); + arg_types, arg_names, arg_mappers, nullptr); HandleTargetOutcome(rc == OFFLOAD_SUCCESS); } @@ -212,14 +212,14 @@ #ifdef OMPTARGET_DEBUG for (int i=0; iaddr /*HstPtrBegin*/, (uintptr_t)CurrHostEntry->addr + CurrHostEntry->size /*HstPtrEnd*/, (uintptr_t)CurrDeviceEntry->addr /*TgtPtrBegin*/, + nullptr, true /*IsRefCountINF*/); } } @@ -158,8 +159,8 @@ DP("Has pending ctors... call now\n"); for (auto &entry : lib.second.PendingCtors) { void *ctor = entry; - int rc = target(device_id, ctor, 0, NULL, NULL, NULL, NULL, NULL, 1, - 1, true /*team*/); + int rc = target(device_id, ctor, 0, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, 1, 1, true /*team*/); if (rc != OFFLOAD_SUCCESS) { REPORT("Running ctor " DPxMOD " failed.\n", DPxPTR(ctor)); Device.PendingGlobalsMtx.unlock(); @@ -240,7 +241,7 @@ int rc = target_data_function(Device, MapperComponents.Components.size(), MapperArgsBase.data(), MapperArgs.data(), MapperArgSizes.data(), MapperArgTypes.data(), - /*arg_mappers*/ nullptr, + /*arg_names*/ nullptr, /*arg_mappers*/ nullptr, /*__tgt_async_info*/ nullptr); return rc; @@ -249,7 +250,7 @@ /// Internal function to do the mapping and transfer the data to the device int targetDataBegin(DeviceTy &Device, int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types, - void **arg_mappers, __tgt_async_info *async_info_ptr) { + void **arg_names, void **arg_mappers, __tgt_async_info *async_info_ptr) { // process each input. for (int32_t i = 0; i < arg_num; ++i) { // Ignore private variables and arrays - there is no mapping for them. @@ -279,6 +280,7 @@ void *HstPtrBegin = args[i]; void *HstPtrBase = args_base[i]; int64_t data_size = arg_sizes[i]; + void *HstPtrName = (!arg_names) ? nullptr : arg_names[i]; // Adjust for proper alignment if this is a combined entry (for structs). // Look at the next argument - if that is MEMBER_OF this one, then this one @@ -327,7 +329,7 @@ // PTR_AND_OBJ entry is handled below, and so the allocation might fail // when HasPresentModifier. PointerTgtPtrBegin = Device.getOrAllocTgtPtr( - HstPtrBase, HstPtrBase, sizeof(void *), Pointer_IsNew, IsHostPtr, + HstPtrBase, HstPtrBase, sizeof(void *), HstPtrName, Pointer_IsNew, IsHostPtr, IsImplicit, UpdateRef, HasCloseModifier, HasPresentModifier); if (!PointerTgtPtrBegin) { REPORT("Call to getOrAllocTgtPtr returned null pointer (%s).\n", @@ -345,8 +347,8 @@ } void *TgtPtrBegin = Device.getOrAllocTgtPtr( - HstPtrBegin, HstPtrBase, data_size, IsNew, IsHostPtr, IsImplicit, - UpdateRef, HasCloseModifier, HasPresentModifier); + HstPtrBegin, HstPtrBase, data_size, HstPtrName, IsNew, IsHostPtr, + IsImplicit, UpdateRef, HasCloseModifier, HasPresentModifier); // If data_size==0, then the argument could be a zero-length pointer to // NULL, so getOrAlloc() returning NULL is not an error. if (!TgtPtrBegin && (data_size || HasPresentModifier)) { @@ -443,7 +445,8 @@ /// Internal function to undo the mapping and retrieve the data from the device. int targetDataEnd(DeviceTy &Device, int32_t ArgNum, void **ArgBases, void **Args, int64_t *ArgSizes, int64_t *ArgTypes, - void **ArgMappers, __tgt_async_info *AsyncInfo) { + void **ArgNames, void **ArgMappers, + __tgt_async_info *AsyncInfo) { int Ret; std::vector DeallocTgtPtrs; // process each input. @@ -640,7 +643,7 @@ // same signature as targetDataBegin and targetDataEnd. int target_data_update(DeviceTy &Device, int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types, - void **arg_mappers, __tgt_async_info *async_info_ptr) { + void **arg_names, void **arg_mappers, __tgt_async_info *async_info_ptr) { // process each input. for (int32_t i = 0; i < arg_num; ++i) { if ((arg_types[i] & OMP_TGT_MAPTYPE_LITERAL) || @@ -832,10 +835,14 @@ const char *HstPtrEnd; /// Aligned size const int64_t AlignedSize; + /// Host pointer name + const char *HstPtrName = nullptr; - FirstPrivateArgInfoTy(int Index, const void *HstPtr, int64_t Size) + FirstPrivateArgInfoTy(int Index, const void *HstPtr, int64_t Size, + const void *HstPtrName = nullptr) : Index(Index), HstPtrBegin(reinterpret_cast(HstPtr)), - HstPtrEnd(HstPtrBegin + Size), AlignedSize(Size + Size % Alignment) {} + HstPtrEnd(HstPtrBegin + Size), AlignedSize(Size + Size % Alignment), + HstPtrName(reinterpret_cast(HstPtrName)) {} }; /// A vector of target pointers for all private arguments @@ -863,9 +870,10 @@ PrivateArgumentManagerTy(DeviceTy &Dev, __tgt_async_info *AsyncInfo) : Device(Dev), AsyncInfo(AsyncInfo) {} - /// A a private argument + /// Add a private argument int addArg(void *HstPtr, int64_t ArgSize, int64_t ArgOffset, - bool IsFirstPrivate, void *&TgtPtr, int TgtArgsIndex) { + bool IsFirstPrivate, void *&TgtPtr, int TgtArgsIndex, + const void *HstPtrName = nullptr) { // If the argument is not first-private, or its size is greater than a // predefined threshold, we will allocate memory and issue the transfer // immediately. @@ -909,7 +917,7 @@ // Placeholder value TgtPtr = nullptr; - FirstPrivateArgInfo.emplace_back(TgtArgsIndex, HstPtr, ArgSize); + FirstPrivateArgInfo.emplace_back(TgtArgsIndex, HstPtr, ArgSize, HstPtrName); FirstPrivateArgSize += FirstPrivateArgInfo.back().AlignedSize; } @@ -984,14 +992,14 @@ /// variables. int processDataBefore(int64_t DeviceId, void *HostPtr, int32_t ArgNum, void **ArgBases, void **Args, int64_t *ArgSizes, - int64_t *ArgTypes, void **ArgMappers, + int64_t *ArgTypes, void **ArgNames, void **ArgMappers, std::vector &TgtArgs, std::vector &TgtOffsets, PrivateArgumentManagerTy &PrivateArgumentManager, __tgt_async_info *AsyncInfo) { DeviceTy &Device = Devices[DeviceId]; int Ret = targetDataBegin(Device, ArgNum, ArgBases, Args, ArgSizes, ArgTypes, - ArgMappers, AsyncInfo); + ArgNames, ArgMappers, AsyncInfo); if (Ret != OFFLOAD_SUCCESS) { REPORT("Call to targetDataBegin failed, abort target.\n"); return OFFLOAD_FAIL; @@ -1049,6 +1057,7 @@ void *HstPtrBegin = Args[I]; void *HstPtrBase = ArgBases[I]; void *TgtPtrBegin; + void *HstPtrName = (!ArgNames) ? nullptr : ArgNames[I]; ptrdiff_t TgtBaseOffset; bool IsLast, IsHostPtr; // unused. if (ArgTypes[I] & OMP_TGT_MAPTYPE_LITERAL) { @@ -1064,7 +1073,8 @@ (I >= ArgNum - 1 || !(ArgTypes[I + 1] & OMP_TGT_MAPTYPE_MEMBER_OF)); Ret = PrivateArgumentManager.addArg(HstPtrBegin, ArgSizes[I], TgtBaseOffset, IsFirstPrivate, - TgtPtrBegin, TgtArgs.size()); + TgtPtrBegin, TgtArgs.size(), + HstPtrName); if (Ret != OFFLOAD_SUCCESS) { REPORT("Failed to process %sprivate argument " DPxMOD "\n", (IsFirstPrivate ? "first-" : ""), DPxPTR(HstPtrBegin)); @@ -1104,14 +1114,14 @@ /// host if needed and deallocating target memory of (first-)private variables. int processDataAfter(int64_t DeviceId, void *HostPtr, int32_t ArgNum, void **ArgBases, void **Args, int64_t *ArgSizes, - int64_t *ArgTypes, void **ArgMappers, + int64_t *ArgTypes, void **ArgNames, void **ArgMappers, PrivateArgumentManagerTy &PrivateArgumentManager, __tgt_async_info *AsyncInfo) { DeviceTy &Device = Devices[DeviceId]; // Move data from device. int Ret = targetDataEnd(Device, ArgNum, ArgBases, Args, ArgSizes, ArgTypes, - ArgMappers, AsyncInfo); + ArgNames, ArgMappers, AsyncInfo); if (Ret != OFFLOAD_SUCCESS) { REPORT("Call to targetDataEnd failed, abort target.\n"); return OFFLOAD_FAIL; @@ -1135,8 +1145,8 @@ /// returns 0 if it was able to transfer the execution to a target and an /// integer different from zero otherwise. int target(int64_t DeviceId, void *HostPtr, int32_t ArgNum, void **ArgBases, - void **Args, int64_t *ArgSizes, int64_t *ArgTypes, void **ArgMappers, - int32_t TeamNum, int32_t ThreadLimit, int IsTeamConstruct) { + void **Args, int64_t *ArgSizes, int64_t *ArgTypes, void **ArgNames, + void **ArgMappers, int32_t TeamNum, int32_t ThreadLimit, int IsTeamConstruct) { DeviceTy &Device = Devices[DeviceId]; TableMap *TM = getTableMap(HostPtr); @@ -1166,7 +1176,7 @@ // Process data, such as data mapping, before launching the kernel int Ret = processDataBefore(DeviceId, HostPtr, ArgNum, ArgBases, Args, - ArgSizes, ArgTypes, ArgMappers, TgtArgs, + ArgSizes, ArgTypes, ArgNames, ArgMappers, TgtArgs, TgtOffsets, PrivateArgumentManager, &AsyncInfo); if (Ret != OFFLOAD_SUCCESS) { REPORT("Failed to process data before launching the kernel.\n"); @@ -1197,7 +1207,7 @@ // Transfer data back and deallocate target memory for (first-)private // variables Ret = processDataAfter(DeviceId, HostPtr, ArgNum, ArgBases, Args, ArgSizes, - ArgTypes, ArgMappers, PrivateArgumentManager, + ArgTypes, ArgNames, ArgMappers, PrivateArgumentManager, &AsyncInfo); if (Ret != OFFLOAD_SUCCESS) { REPORT("Failed to process data after launching the kernel.\n"); diff --git a/openmp/libomptarget/src/private.h b/openmp/libomptarget/src/private.h --- a/openmp/libomptarget/src/private.h +++ b/openmp/libomptarget/src/private.h @@ -20,22 +20,22 @@ extern int targetDataBegin(DeviceTy &Device, int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types, - void **arg_mappers, + void **arg_names, void **arg_mappers, __tgt_async_info *async_info_ptr); extern int targetDataEnd(DeviceTy &Device, int32_t ArgNum, void **ArgBases, void **Args, int64_t *ArgSizes, int64_t *ArgTypes, - void **ArgMappers, __tgt_async_info *AsyncInfo); + void **arg_names, void **ArgMappers, __tgt_async_info *AsyncInfo); extern int target_data_update(DeviceTy &Device, int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types, - void **arg_mappers, + void **arg_names, void **arg_mappers, __tgt_async_info *async_info_ptr = nullptr); extern int target(int64_t DeviceId, void *HostPtr, int32_t ArgNum, void **ArgBases, void **Args, int64_t *ArgSizes, - int64_t *ArgTypes, void **ArgMappers, int32_t TeamNum, + int64_t *ArgTypes, void **arg_names, void **ArgMappers, int32_t TeamNum, int32_t ThreadLimit, int IsTeamConstruct); extern int CheckDeviceAndCtors(int64_t device_id); @@ -77,7 +77,7 @@ // Function pointer type for target_data_* functions (targetDataBegin, // targetDataEnd and target_data_update). typedef int (*TargetDataFuncPtrTy)(DeviceTy &, int32_t, void **, void **, - int64_t *, int64_t *, void **, + int64_t *, int64_t *, void **, void **, __tgt_async_info *); // Implemented in libomp, they are called from within __tgt_* functions. @@ -103,12 +103,13 @@ return; fprintf(stderr, "Device %d Host-Device Pointer Mappings:\n", Device.DeviceID); - fprintf(stderr, "%-18s %-18s %s\n", "Host Ptr", "Target Ptr", "Size (B)"); + fprintf(stderr, "%-18s %-18s %s %s\n", "Host Ptr", "Target Ptr", "Size (B)", "Name"); for (const auto &HostTargetMap : Device.HostDataToTargetMap) { - fprintf(stderr, DPxMOD " " DPxMOD " %lu\n", + fprintf(stderr, DPxMOD " " DPxMOD " %lu %s\n", DPxPTR(HostTargetMap.HstPtrBegin), DPxPTR(HostTargetMap.TgtPtrBegin), - HostTargetMap.HstPtrEnd - HostTargetMap.HstPtrBegin); + HostTargetMap.HstPtrEnd - HostTargetMap.HstPtrBegin, + getName(HostTargetMap.HstPtrName).c_str()); } } diff --git a/openmp/libomptarget/src/rtl.cpp b/openmp/libomptarget/src/rtl.cpp --- a/openmp/libomptarget/src/rtl.cpp +++ b/openmp/libomptarget/src/rtl.cpp @@ -383,8 +383,8 @@ Device.PendingGlobalsMtx.lock(); if (Device.PendingCtorsDtors[desc].PendingCtors.empty()) { for (auto &dtor : Device.PendingCtorsDtors[desc].PendingDtors) { - int rc = target(Device.DeviceID, dtor, 0, NULL, NULL, NULL, NULL, - NULL, 1, 1, true /*team*/); + int rc = target(Device.DeviceID, dtor, 0, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, 1, 1, true /*team*/); if (rc != OFFLOAD_SUCCESS) { DP("Running destructor " DPxMOD " failed.\n", DPxPTR(dtor)); }