diff --git a/openmp/CMakeLists.txt b/openmp/CMakeLists.txt --- a/openmp/CMakeLists.txt +++ b/openmp/CMakeLists.txt @@ -71,6 +71,9 @@ # to enable time profiling support in the OpenMP runtime. add_subdirectory(runtime) +# Build libompd.so +add_subdirectory(libompd) + if (OPENMP_ENABLE_LIBOMPTARGET) # Check that the library can actually be built. if (APPLE OR WIN32) diff --git a/openmp/libompd/.clang-tidy b/openmp/libompd/.clang-tidy new file mode 100644 --- /dev/null +++ b/openmp/libompd/.clang-tidy @@ -0,0 +1,2 @@ +# Checks enabled in the top-level .clang-tidy minus readability-identifier-naming and llvm-header-guard. +Checks: '-*,clang-diagnostic-*,llvm-*,-llvm-header-guard,misc-*,-misc-unused-parameters,-misc-non-private-member-variables-in-classes' diff --git a/openmp/libompd/CMakeLists.txt b/openmp/libompd/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/openmp/libompd/CMakeLists.txt @@ -0,0 +1,14 @@ +# +#//===----------------------------------------------------------------------===// +#// +#// 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 +#// +#//===----------------------------------------------------------------------===// +# + +if(LIBOMP_OMPD_SUPPORT) + set(OMPD_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/) + add_subdirectory(src) +endif() diff --git a/openmp/libompd/src/CMakeLists.txt b/openmp/libompd/src/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/openmp/libompd/src/CMakeLists.txt @@ -0,0 +1,50 @@ +# +#//===----------------------------------------------------------------------===// +#// +#// 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 +#// +#//===----------------------------------------------------------------------===// +# + +project (libompd) +cmake_minimum_required(VERSION 3.13.4) + +add_library (ompd SHARED TargetValue.cpp) + +add_dependencies(ompd omp) # ensure generated import library is created first + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +set(LIBOMPD_LD_STD_FLAGS FALSE CACHE BOOL + "Use -stdlibc++ instead of -libc++ library for C++ ") + +if(${LIBOMPD_LD_STD_FLAGS}) +# Find and replace/add libstdc++ to compile flags + STRING( FIND "${CMAKE_CXX_FLAGS}" "-stdlib=libc++" OUT ) + if("${OUT}" STREQUAL "-1" ) + set (CMAKE_CXX_FLAGS "-stdlib=libstdc++ ${CMAKE_CXX_FLAGS}") + else() + STRING( REPLACE "-stdlib=libc++" "-stdlib=libstdc++" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ) + endif() + +# Find and replace/add libstdc++ to loader flags + STRING( FIND "${CMAKE_SHARED_LINKER_FLAGS}" "-stdlib=libc++" OUT ) + if("${OUT}" STREQUAL "-1" ) + set (CMAKE_SHARED_LINKER_FLAGS "-stdlib=libstdc++ ${CMAKE_SHARED_LINKER_FLAGS}") + else() + STRING( REPLACE "-stdlib=libc++" "-stdlib=libstdc++" CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} ) + endif() +endif() + +include_directories ( + ${CMAKE_CURRENT_SOURCE_DIR} + ${LIBOMP_INCLUDE_DIR} + ${LIBOMP_SRC_DIR} +) + +INSTALL( TARGETS ompd + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib/static + RUNTIME DESTINATION bin ) diff --git a/openmp/libompd/src/Debug.h b/openmp/libompd/src/Debug.h new file mode 100644 --- /dev/null +++ b/openmp/libompd/src/Debug.h @@ -0,0 +1,57 @@ +/* + * Debug.h -- OMP debug + */ + +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include +#include + +#ifndef GDB_DEBUG_H_ +#define GDB_DEBUG_H_ + +namespace GdbColor { +enum Code { + FG_RED = 31, + FG_GREEN = 32, + FG_BLUE = 34, + FG_DEFAULT = 39, + BG_RED = 41, + BG_GREEN = 42, + BG_BLUE = 44, + BG_DEFAULT = 49 +}; +inline std::ostream &operator<<(std::ostream &os, Code code) { + return os << "\033[" << static_cast(code) << "m"; +} +} // namespace GdbColor + +class ColorOut { +private: + std::ostream &out; + GdbColor::Code color; + +public: + ColorOut(std::ostream &_out, GdbColor::Code _color) + : out(_out), color(_color) {} + template const ColorOut &operator<<(const T &val) const { + out << color << val << GdbColor::FG_DEFAULT; + return *this; + } + const ColorOut &operator<<(std::ostream &(*pf)(std::ostream &)) const { + out << color << pf << GdbColor::FG_DEFAULT; + return *this; + } +}; + +static ColorOut dout(std::cout, GdbColor::FG_RED); +static ColorOut sout(std::cout, GdbColor::FG_GREEN); +static ColorOut hout(std::cout, GdbColor::FG_BLUE); + +#endif /*GDB_DEBUG_H_*/ diff --git a/openmp/libompd/src/TargetValue.h b/openmp/libompd/src/TargetValue.h new file mode 100644 --- /dev/null +++ b/openmp/libompd/src/TargetValue.h @@ -0,0 +1,259 @@ +/* + * TargetValue.h -- Access to target values using OMPD callbacks + */ + +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "omp-tools.h" +#include "ompd-private.h" +#include + +#ifndef SRC_TARGET_VALUE_H_ +#define SRC_TARGET_VALUE_H_ + +#ifdef __cplusplus + +#include +#include +#include + +class TType; +class TValue; +class TBaseValue; + +class TTypeFactory { +protected: + std::map> + ttypes; + +public: + TTypeFactory() : ttypes() {} + TType &getType(ompd_address_space_context_t *context, const char *typName, + ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED); +}; + +static thread_local TTypeFactory tf = TTypeFactory(); + +class TType { +protected: + ompd_size_t typeSize; + std::map fieldOffsets; + std::map fieldSizes; + std::map bitfieldMasks; + ompd_addr_t descSegment; + const char *typeName; + ompd_address_space_context_t *context; + bool isvoid; + TType(ompd_address_space_context_t *context, const char *typeName, + ompd_addr_t _segment = OMPD_SEGMENT_UNSPECIFIED); + +public: + TType(bool, ompd_addr_t _segment = OMPD_SEGMENT_UNSPECIFIED) + : descSegment(_segment), isvoid(true) {} + bool isVoid() const { return isvoid; } + ompd_rc_t getElementOffset(const char *fieldName, ompd_size_t *offset); + ompd_rc_t getElementSize(const char *fieldName, ompd_size_t *size); + ompd_rc_t getBitfieldMask(const char *fieldName, uint64_t *bitfieldmask); + ompd_rc_t getSize(ompd_size_t *size); + friend TValue; + friend TTypeFactory; +}; + +static TType nullType(true); + +/** + * class TError + * As TValue is designed to concatenate operations, we use TError + * to catch errors that might happen on each operation and provide + * the according error code and which operation raised the error. + */ + +class TError { +protected: + ompd_rc_t errorCode; + TError() : errorCode(ompd_rc_ok) {} + TError(const ompd_rc_t &error) : errorCode(error) {} + +public: + std::string toString() { + return std::string("TError messages not implemented yet"); + } + friend TValue; + friend TBaseValue; +}; + +/** + * class TValue + * This class encapsules the access to target values by using OMPD + * callback functions. The member functions are designed to concatenate + * the operations that are needed to access values from structures + * e.g., _a[6]->_b._c would read like : + * TValue(ctx, + * "_a").cast("A",2).getArrayElement(6).access("_b").cast("B").access("_c") + */ + +class TValue { +protected: + TError errorState; + TType *type; + int pointerLevel; + ompd_address_space_context_t *context; + ompd_thread_context_t *tcontext; + ompd_address_t symbolAddr; + ompd_size_t fieldSize; + +public: + static const ompd_callbacks_t *callbacks; + static ompd_device_type_sizes_t type_sizes; + + TValue() : errorState(ompd_rc_error) {} + /** + * Create a target value object from symbol name + */ + TValue(ompd_address_space_context_t *_context, const char *_valueName, + ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED) + : TValue(_context, NULL, _valueName, segment) {} + + TValue(ompd_address_space_context_t *context, ompd_thread_context_t *tcontext, + const char *valueName, ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED); + /** + * Create a target value object from target value address + */ + TValue(ompd_address_space_context_t *_context, ompd_address_t _addr) + : TValue(_context, NULL, _addr) {} + TValue(ompd_address_space_context_t *context, ompd_thread_context_t *tcontext, + ompd_address_t addr); + /** + * Cast the target value object to some type of typeName + * + * This call modifies the object and returns a reference to the modified + * object + */ + TValue &cast(const char *typeName); + + /** + * Cast the target value object to some pointer of type typename + * pointerlevel gives the number of * + * e.g., char** would be: cast("char",2) + * + * This call modifies the object and returns a reference to the modified + * object + */ + TValue &cast(const char *typeName, int pointerLevel, + ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED); + + /** + * Get the target address of the target value + */ + ompd_rc_t getAddress(ompd_address_t *addr) const; + /** + * Get the raw memory copy of the target value + */ + ompd_rc_t getRawValue(void *buf, int count); + /** + * Fetch a string copy from the target. "this" represents the pointer + * that holds the value of a null terminated character string. "buf" + * points to the destination string to be allocated and copied to. + * Returns 'ompd_rc_error' to signify a truncated string or a target + * read error. + */ + ompd_rc_t getString(const char **buf); + /** + * Get a new target value object for the dereferenced target value + * reduces the pointer level, uses the target value as new target address, + * keeps the target type + */ + TValue dereference() const; + /** + * Cast to a base type + * Only values of base type may be read from target + */ + TBaseValue castBase(ompd_target_prim_types_t baseType) const; + /** + * Cast to a base type + * Get the size by fieldsize from runtime + */ + TBaseValue castBase() const; + /** + * Cast to a base type + * Get the size by name from the rtl + */ + TBaseValue castBase(const char *varName); + /** + * Resolve field access for structs/unions + * this supports both "->" and "." operator. + */ + TValue access(const char *fieldName) const; + /** + * Tests for a field bit in a bitfield + */ + ompd_rc_t check(const char *bitfieldName, ompd_word_t *isSet) const; + /** + * Get an array element + */ + TValue getArrayElement(int elemNumber) const; + /** + * Get an element of a pointer array + */ + TValue getPtrArrayElement(int elemNumber) const; + /** + * Did we raise some error yet? + */ + bool gotError() const { return errorState.errorCode != ompd_rc_ok; } + /** + * Get the error code + */ + ompd_rc_t getError() const { return errorState.errorCode; } + /** + * Did we raise some error yet? + */ + std::string getErrorMessage() { return errorState.toString(); } +}; + +class TBaseValue : public TValue { +protected: + ompd_size_t baseTypeSize = 0; + TBaseValue(const TValue &, ompd_target_prim_types_t baseType); + TBaseValue(const TValue &, ompd_size_t baseTypeSize); + +public: + ompd_rc_t getValue(void *buf, int count); + template ompd_rc_t getValue(T &buf); + + friend TValue; +}; + +template ompd_rc_t TBaseValue::getValue(T &buf) { + assert(sizeof(T) >= baseTypeSize); + ompd_rc_t ret = getValue(&buf, 1); + if (sizeof(T) > baseTypeSize) { + switch (baseTypeSize) { + case 1: + buf = (T) * ((int8_t *)&buf); + break; + case 2: + buf = (T) * ((int16_t *)&buf); + break; + case 4: + buf = (T) * ((int32_t *)&buf); + break; + case 8: + buf = (T) * ((int64_t *)&buf); + break; + } + } + return ret; +} + +#define EXTERN_C extern "C" +#else +#define EXTERN_C +#endif + +#endif /*SRC_TARGET_VALUE_H_*/ diff --git a/openmp/libompd/src/TargetValue.cpp b/openmp/libompd/src/TargetValue.cpp new file mode 100644 --- /dev/null +++ b/openmp/libompd/src/TargetValue.cpp @@ -0,0 +1,408 @@ +/* + * TargetValue.cpp -- Access to target values using OMPD callbacks + */ + +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "TargetValue.h" +#include "Debug.h" +#include +#include +#include +#include + +const ompd_callbacks_t *TValue::callbacks = NULL; +ompd_device_type_sizes_t TValue::type_sizes; + +inline int ompd_sizeof(ompd_target_prim_types_t t) { + assert(t != ompd_type_max && "ompd_type_max should not be used anywhere"); + assert(t != ompd_type_invalid && "request size of invalid type"); + + return (((char *)&TValue::type_sizes)[(int)t]); +} + +TType &TTypeFactory::getType(ompd_address_space_context_t *context, + const char *typeName, ompd_addr_t segment) { + TType empty(true); + + if (ttypes.find(context) == ttypes.end()) { + std::map empty; + ttypes[context] = empty; + } + + auto t = ttypes.find(context); + auto i = t->second.find(typeName); + if (i == t->second.end()) + i = t->second.insert( + i, std::make_pair(typeName, TType(context, typeName, segment))); + else + i->second.context = context; + + return i->second; +} + +TType::TType(ompd_address_space_context_t *_context, const char *_typeName, + ompd_addr_t _segment) + : typeSize(0), fieldOffsets(), descSegment(_segment), typeName(_typeName), + context(_context), isvoid(false) {} + +ompd_rc_t TType::getSize(ompd_size_t *size) { + ompd_rc_t ret = ompd_rc_ok; + if (typeSize == 0) { + ompd_address_t symbolAddr; + ompd_size_t tmpSize; + std::stringstream ss; + ss << "ompd_sizeof__" << typeName; + + ret = TValue::callbacks->symbol_addr_lookup(context, NULL, ss.str().c_str(), + &symbolAddr, NULL); + if (ret != ompd_rc_ok) { + dout << "missing symbol " << ss.str() + << " add this to ompd-specific.h:\nOMPD_SIZEOF(" << typeName + << ") \\" << std::endl; + return ret; + } + + symbolAddr.segment = descSegment; + + ret = TValue::callbacks->read_memory( + context, NULL, &symbolAddr, 1 * TValue::type_sizes.sizeof_long_long, + &(tmpSize)); + if (ret != ompd_rc_ok) + return ret; + ret = TValue::callbacks->device_to_host( + context, &tmpSize, TValue::type_sizes.sizeof_long_long, 1, &(typeSize)); + } + *size = typeSize; + return ret; +} + +ompd_rc_t TType::getBitfieldMask(const char *fieldName, + uint64_t *bitfieldmask) { + ompd_rc_t ret = ompd_rc_ok; + auto i = bitfieldMasks.find(fieldName); + if (i == bitfieldMasks.end()) { + uint64_t tmpMask, bitfieldMask; + ompd_address_t symbolAddr; + std::stringstream ss; + ss << "ompd_bitfield__" << typeName << "__" << fieldName; + ret = TValue::callbacks->symbol_addr_lookup(context, NULL, ss.str().c_str(), + &symbolAddr, NULL); + if (ret != ompd_rc_ok) { + dout << "missing symbol " << ss.str() + << " add this to ompd-specific.h:\nOMPD_BITFIELD(" << typeName << "," + << fieldName << ") \\" << std::endl; + return ret; + } + symbolAddr.segment = descSegment; + + ret = TValue::callbacks->read_memory( + context, NULL, &symbolAddr, 1 * TValue::type_sizes.sizeof_long_long, + &(tmpMask)); + if (ret != ompd_rc_ok) + return ret; + ret = TValue::callbacks->device_to_host(context, &(tmpMask), + TValue::type_sizes.sizeof_long_long, + 1, &(bitfieldMask)); + if (ret != ompd_rc_ok) { + return ret; + } + i = bitfieldMasks.insert(i, std::make_pair(fieldName, bitfieldMask)); + } + *bitfieldmask = i->second; + return ret; +} + +ompd_rc_t TType::getElementOffset(const char *fieldName, ompd_size_t *offset) { + ompd_rc_t ret = ompd_rc_ok; + auto i = fieldOffsets.find(fieldName); + if (i == fieldOffsets.end()) { + ompd_size_t tmpOffset, fieldOffset; + ompd_address_t symbolAddr; + std::stringstream ss; + ss << "ompd_access__" << typeName << "__" << fieldName; + + ret = TValue::callbacks->symbol_addr_lookup(context, NULL, ss.str().c_str(), + &symbolAddr, NULL); + if (ret != ompd_rc_ok) { + dout << "missing symbol " << ss.str() + << " add this to ompd-specific.h:\nOMPD_ACCESS(" << typeName << "," + << fieldName << ") \\" << std::endl; + return ret; + } + symbolAddr.segment = descSegment; + + ret = TValue::callbacks->read_memory( + context, NULL, &symbolAddr, 1 * TValue::type_sizes.sizeof_long_long, + &(tmpOffset)); + if (ret != ompd_rc_ok) + return ret; + ret = TValue::callbacks->device_to_host(context, &(tmpOffset), + TValue::type_sizes.sizeof_long_long, + 1, &fieldOffset); + if (ret != ompd_rc_ok) { + return ret; + } + i = fieldOffsets.insert(i, std::make_pair(fieldName, fieldOffset)); + } + *offset = i->second; + return ret; +} + +ompd_rc_t TType::getElementSize(const char *fieldName, ompd_size_t *size) { + ompd_rc_t ret = ompd_rc_ok; + auto i = fieldSizes.find(fieldName); + if (i == fieldSizes.end()) { + ompd_size_t tmpOffset, fieldSize; + ompd_address_t symbolAddr; + std::stringstream ss; + ss << "ompd_sizeof__" << typeName << "__" << fieldName; + + ret = TValue::callbacks->symbol_addr_lookup(context, NULL, ss.str().c_str(), + &symbolAddr, NULL); + if (ret != ompd_rc_ok) { + dout << "missing symbol " << ss.str() + << " add this to ompd-specific.h:\nOMPD_ACCESS(" << typeName << "," + << fieldName << ") \\" << std::endl; + return ret; + } + symbolAddr.segment = descSegment; + + ret = TValue::callbacks->read_memory( + context, NULL, &symbolAddr, 1 * TValue::type_sizes.sizeof_long_long, + &(tmpOffset)); + if (ret != ompd_rc_ok) + return ret; + ret = TValue::callbacks->device_to_host(context, &tmpOffset, + TValue::type_sizes.sizeof_long_long, + 1, &fieldSize); + if (ret != ompd_rc_ok) { + return ret; + } + i = fieldSizes.insert(i, std::make_pair(fieldName, fieldSize)); + } + *size = i->second; + return ret; +} + +TValue::TValue(ompd_address_space_context_t *_context, + ompd_thread_context_t *_tcontext, const char *_valueName, + ompd_addr_t segment) + : errorState(ompd_rc_ok), type(&nullType), pointerLevel(0), + context(_context), tcontext(_tcontext), fieldSize(0) { + errorState.errorCode = callbacks->symbol_addr_lookup( + context, tcontext, _valueName, &symbolAddr, NULL); + symbolAddr.segment = segment; +} + +TValue::TValue(ompd_address_space_context_t *_context, + ompd_thread_context_t *_tcontext, ompd_address_t addr) + : errorState(ompd_rc_ok), type(&nullType), pointerLevel(0), + context(_context), tcontext(_tcontext), symbolAddr(addr), fieldSize(0) { + if (addr.address == 0) + errorState.errorCode = ompd_rc_bad_input; +} + +TValue &TValue::cast(const char *typeName) { + if (gotError()) + return *this; + type = &tf.getType(context, typeName, symbolAddr.segment); + pointerLevel = 0; + assert(!type->isVoid() && "cast to invalid type failed"); + return *this; +} + +TValue &TValue::cast(const char *typeName, int _pointerLevel, + ompd_addr_t segment) { + if (gotError()) + return *this; + type = &tf.getType(context, typeName, symbolAddr.segment); + pointerLevel = _pointerLevel; + symbolAddr.segment = segment; + assert(!type->isVoid() && "cast to invalid type failed"); + return *this; +} + +TValue TValue::dereference() const { + if (gotError()) + return *this; + ompd_address_t tmpAddr; + assert(!type->isVoid() && "cannot work with void"); + assert(pointerLevel > 0 && "cannot dereference non-pointer"); + TValue ret = *this; + ret.pointerLevel--; + ret.errorState.errorCode = callbacks->read_memory( + context, tcontext, &symbolAddr, 1 * TValue::type_sizes.sizeof_pointer, + &(tmpAddr.address)); + if (ret.errorState.errorCode != ompd_rc_ok) + return ret; + + ret.errorState.errorCode = callbacks->device_to_host( + context, &(tmpAddr.address), TValue::type_sizes.sizeof_pointer, 1, + &(ret.symbolAddr.address)); + if (ret.errorState.errorCode != ompd_rc_ok) { + return ret; + } + if (ret.symbolAddr.address == 0) + ret.errorState.errorCode = ompd_rc_unsupported; + return ret; +} + +ompd_rc_t TValue::getAddress(ompd_address_t *addr) const { + *addr = symbolAddr; + if (symbolAddr.address == 0) + return ompd_rc_unsupported; + return errorState.errorCode; +} + +ompd_rc_t TValue::getRawValue(void *buf, int count) { + if (errorState.errorCode != ompd_rc_ok) + return errorState.errorCode; + ompd_size_t size; + errorState.errorCode = type->getSize(&size); + if (errorState.errorCode != ompd_rc_ok) + return errorState.errorCode; + + errorState.errorCode = + callbacks->read_memory(context, tcontext, &symbolAddr, size, buf); + return errorState.errorCode; +} + +ompd_rc_t TValue::getString(const char **buf) { + *buf = 0; + if (gotError()) + return getError(); + + TValue strValue = dereference(); + if (strValue.gotError()) { + return strValue.getError(); + } + + if (!callbacks) { + return ompd_rc_error; + } + ompd_rc_t ret; +#define BUF_LEN 512 + char *string_buffer; + + // Allocate an extra byte, but pass only BUF_LEN to the tool + // so that we can detect truncation later. + ret = callbacks->alloc_memory(BUF_LEN + 1, (void **)&string_buffer); + if (ret != ompd_rc_ok) { + return ret; + } + string_buffer[BUF_LEN] = '\0'; + + // TODO: if we have not read in the complete string, we need to realloc + // 'string_buffer' and attempt reading again repeatedly till the entire string + // is read in. + ret = callbacks->read_string(context, tcontext, &strValue.symbolAddr, BUF_LEN, + (void *)string_buffer); + *buf = string_buffer; + // Check for truncation. The standard specifies that if a null byte is not + // among the first 'nbytes' bytes, the string placed in the buffer is not + // null-terminated. 'nbytes' is BUF_LEN in this case. + if (ret == ompd_rc_ok && strlen(string_buffer) == BUF_LEN) { + return ompd_rc_error; + } + return ret; +} + +TBaseValue TValue::castBase(const char *varName) { + ompd_size_t size; + errorState.errorCode = + tf.getType(context, varName, symbolAddr.segment).getSize(&size); + return TBaseValue(*this, size); +} + +TBaseValue TValue::castBase() const { + if (pointerLevel > 0) + return TBaseValue(*this, type_sizes.sizeof_pointer); + return TBaseValue(*this, fieldSize); +} + +TBaseValue TValue::castBase(ompd_target_prim_types_t baseType) const { + return TBaseValue(*this, baseType); +} + +TValue TValue::access(const char *fieldName) const { + if (gotError()) + return *this; + TValue ret = *this; + assert(pointerLevel < 2 && "access to field element of pointer array failed"); + if (pointerLevel == 1) // -> operator + ret = ret.dereference(); + // we use *this for . operator + ompd_size_t offset; + ret.errorState.errorCode = type->getElementOffset(fieldName, &offset); + ret.errorState.errorCode = type->getElementSize(fieldName, &(ret.fieldSize)); + ret.symbolAddr.address += offset; + + return ret; +} + +ompd_rc_t TValue::check(const char *bitfieldName, ompd_word_t *isSet) const { + if (gotError()) + return getError(); + int bitfield; + uint64_t bitfieldmask; + ompd_rc_t ret = this->castBase(ompd_type_int).getValue(&bitfield, 1); + if (ret != ompd_rc_ok) + return ret; + ret = type->getBitfieldMask(bitfieldName, &bitfieldmask); + *isSet = ((bitfield & bitfieldmask) != 0); + return ret; +} + +TValue TValue::getArrayElement(int elemNumber) const { + if (gotError()) + return *this; + TValue ret; + if (pointerLevel > 0) { + ret = dereference(); + } else { + ret = *this; + } + if (ret.pointerLevel == 0) { + ompd_size_t size; + ret.errorState.errorCode = type->getSize(&size); + ret.symbolAddr.address += elemNumber * size; + } else { + ret.symbolAddr.address += elemNumber * type_sizes.sizeof_pointer; + } + return ret; +} + +TValue TValue::getPtrArrayElement(int elemNumber) const { + if (gotError()) { + return *this; + } + assert(pointerLevel > 0 && "This only works on arrays of pointers"); + TValue ret = *this; + ret.symbolAddr.address += elemNumber * type_sizes.sizeof_pointer; + return ret; +} + +TBaseValue::TBaseValue(const TValue &_tvalue, + ompd_target_prim_types_t _baseType) + : TValue(_tvalue), baseTypeSize(ompd_sizeof(_baseType)) {} +TBaseValue::TBaseValue(const TValue &_tvalue, ompd_size_t _baseTypeSize) + : TValue(_tvalue), baseTypeSize(_baseTypeSize) {} + +ompd_rc_t TBaseValue::getValue(void *buf, int count) { + if (errorState.errorCode != ompd_rc_ok) + return errorState.errorCode; + errorState.errorCode = callbacks->read_memory(context, tcontext, &symbolAddr, + count * baseTypeSize, buf); + if (errorState.errorCode != ompd_rc_ok) + return errorState.errorCode; + errorState.errorCode = + callbacks->device_to_host(context, buf, baseTypeSize, count, buf); + return errorState.errorCode; +} diff --git a/openmp/libompd/src/ompd-private.h b/openmp/libompd/src/ompd-private.h new file mode 100644 --- /dev/null +++ b/openmp/libompd/src/ompd-private.h @@ -0,0 +1,79 @@ +/* + * ompd-private.h + */ + +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef SRC_OMPD_PRIVATE_H_ +#define SRC_OMPD_PRIVATE_H_ + +/* + * Definition of OMPD states, taken from OMPT + */ +#define FOREACH_OMPD_STATE(macro) \ + \ + /* first available state */ \ + macro(ompt_state_undefined, 0x102) /* undefined thread state */ \ + \ + /* work states (0..15) */ \ + macro(ompt_state_work_serial, 0x000) /* working outside parallel */ \ + macro(ompt_state_work_parallel, 0x001) /* working within parallel */ \ + macro(ompt_state_work_reduction, 0x002) /* performing a reduction */ \ + \ + /* barrier wait states (16..31) */ \ + macro(ompt_state_wait_barrier, 0x010) /* waiting at a barrier */ \ + macro(ompt_state_wait_barrier_implicit_parallel, \ + 0x011) /* implicit barrier at the end of parallel region */ \ + macro(ompt_state_wait_barrier_implicit_workshare, \ + 0x012) /* implicit barrier at the end of worksharing */ \ + macro(ompt_state_wait_barrier_implicit, 0x013) /* implicit barrier */ \ + macro(ompt_state_wait_barrier_explicit, 0x014) /* explicit barrier */ \ + \ + /* task wait states (32..63) */ \ + macro(ompt_state_wait_taskwait, 0x020) /* waiting at a taskwait */ \ + macro(ompt_state_wait_taskgroup, 0x021) /* waiting at a taskgroup */ \ + \ + /* mutex wait states (64..127) */ \ + macro(ompt_state_wait_mutex, 0x040) \ + macro(ompt_state_wait_lock, 0x041) /* waiting for lock */ \ + macro(ompt_state_wait_critical, 0x042) /* waiting for critical */ \ + macro(ompt_state_wait_atomic, 0x043) /* waiting for atomic */ \ + macro(ompt_state_wait_ordered, 0x044) /* waiting for ordered */ \ + \ + /* target wait states (128..255) */ \ + macro(ompt_state_wait_target, 0x080) /* waiting for target region */ \ + macro(ompt_state_wait_target_map, \ + 0x081) /* waiting for target data mapping operation */ \ + macro(ompt_state_wait_target_update, \ + 0x082) /* waiting for target update operation */ \ + \ + /* misc (256..511) */ \ + macro(ompt_state_idle, 0x100) /* waiting for work */ \ + macro(ompt_state_overhead, 0x101) /* overhead excluding wait states */ \ + \ + /* implementation-specific states (512..) */ + +#define OMPD_LAST_OMP_STATE ompt_state_overhead + +/** + * Primitive types. + */ +typedef enum ompd_target_prim_types_t { + ompd_type_invalid = -1, + ompd_type_char = 0, + ompd_type_short = 1, + ompd_type_int = 2, + ompd_type_long = 3, + ompd_type_long_long = 4, + ompd_type_pointer = 5, + ompd_type_max +} ompd_target_prim_types_t; + +#include "ompd-types.h" +#endif /*SRC_OMPD_PRIVATE_H*/ diff --git a/openmp/libompd/src/ompd-types.h b/openmp/libompd/src/ompd-types.h new file mode 100644 --- /dev/null +++ b/openmp/libompd/src/ompd-types.h @@ -0,0 +1,38 @@ +/* + * @@name: ompd-types.h + */ + +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef __OMPD_TYPES_H +#define __OMPD_TYPES_H + +extern "C" { +#include "omp-tools.h" +} + +#define OMPD_TYPES_VERSION 20180906 /* YYYYMMDD Format */ + +/* Kinds of device threads */ +#define OMPD_THREAD_ID_PTHREAD ((ompd_thread_id_t)0) +#define OMPD_THREAD_ID_LWP ((ompd_thread_id_t)1) +#define OMPD_THREAD_ID_WINTHREAD ((ompd_thread_id_t)2) +/* The range of non-standard implementation defined values */ +#define OMPD_THREAD_ID_LO ((ompd_thread_id_t)1000000) +#define OMPD_THREAD_ID_HI ((ompd_thread_id_t)1100000) + +/* Memory Access Segment definitions for Host and Target Devices */ +#define OMPD_SEGMENT_UNSPECIFIED ((ompd_seg_t)0) + +/* Kinds of device device address spaces */ +#define OMPD_DEVICE_KIND_HOST ((ompd_device_t)1) +/* The range of non-standard implementation defined values */ +#define OMPD_DEVICE_IMPL_LO ((ompd_device_t)1000000) +#define OMPD_DEVICE_IMPL_HI ((ompd_device_t)1100000) +#endif