blob: 87e4575885e7da9e6937fcd0b6b2289558b2acfd [file] [log] [blame]
/*
* 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_*/