# 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)
--- /dev/null
+# 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'
--- /dev/null
+#
+#//===----------------------------------------------------------------------===//
+#//
+#// 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()
--- /dev/null
+#
+#//===----------------------------------------------------------------------===//
+#//
+#// 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 )
--- /dev/null
+/*
+ * 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 <iostream>
+#include <ostream>
+
+#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<int>(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 <typename T> 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_*/
--- /dev/null
+/*
+ * 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 <cstring>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
+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<const char *, TType> 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;
+}
--- /dev/null
+/*
+ * 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 <stdlib.h>
+
+#ifndef SRC_TARGET_VALUE_H_
+#define SRC_TARGET_VALUE_H_
+
+#ifdef __cplusplus
+
+#include <cassert>
+#include <map>
+#include <string>
+
+class TType;
+class TValue;
+class TBaseValue;
+
+class TTypeFactory {
+protected:
+ std::map<ompd_address_space_context_t *, std::map<const char *, TType>>
+ 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<const char *, ompd_size_t> fieldOffsets;
+ std::map<const char *, ompd_size_t> fieldSizes;
+ std::map<const char *, uint64_t> 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 <typename T> ompd_rc_t getValue(T &buf);
+
+ friend TValue;
+};
+
+template <typename T> 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_*/
--- /dev/null
+/*
+ * 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*/
--- /dev/null
+/*
+ * @@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