brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.2 KiB · 8818121 Raw
409 lines · cpp
1/*2 * TargetValue.cpp -- Access to target values using OMPD callbacks3 */4 5//===----------------------------------------------------------------------===//6//7// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.8// See https://llvm.org/LICENSE.txt for license information.9// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception10//11//===----------------------------------------------------------------------===//12 13#include "TargetValue.h"14#include "Debug.h"15#include <cstring>16#include <fstream>17#include <iostream>18#include <sstream>19 20const ompd_callbacks_t *TValue::callbacks = NULL;21ompd_device_type_sizes_t TValue::type_sizes;22 23inline int ompd_sizeof(ompd_target_prim_types_t t) {24  assert(t != ompd_type_max && "ompd_type_max should not be used anywhere");25  assert(t != ompd_type_invalid && "request size of invalid type");26 27  return (((char *)&TValue::type_sizes)[(int)t]);28}29 30TType &TTypeFactory::getType(ompd_address_space_context_t *context,31                             const char *typeName, ompd_addr_t segment) {32  TType empty(true);33 34  if (ttypes.find(context) == ttypes.end()) {35    std::map<const char *, TType> empty;36    ttypes[context] = empty;37  }38 39  auto t = ttypes.find(context);40  auto i = t->second.find(typeName);41  if (i == t->second.end())42    i = t->second.insert(43        i, std::make_pair(typeName, TType(context, typeName, segment)));44  else45    i->second.context = context;46 47  return i->second;48}49 50TType::TType(ompd_address_space_context_t *_context, const char *_typeName,51             ompd_addr_t _segment)52    : typeSize(0), fieldOffsets(), descSegment(_segment), typeName(_typeName),53      context(_context), isvoid(false) {}54 55ompd_rc_t TType::getSize(ompd_size_t *size) {56  ompd_rc_t ret = ompd_rc_ok;57  if (typeSize == 0) {58    ompd_address_t symbolAddr;59    ompd_size_t tmpSize;60    std::stringstream ss;61    ss << "ompd_sizeof__" << typeName;62 63    ret = TValue::callbacks->symbol_addr_lookup(context, NULL, ss.str().c_str(),64                                                &symbolAddr, NULL);65    if (ret != ompd_rc_ok) {66      dout << "missing symbol " << ss.str()67           << " add this to ompd-specific.h:\nOMPD_SIZEOF(" << typeName68           << ") \\" << std::endl;69      return ret;70    }71 72    symbolAddr.segment = descSegment;73 74    ret = TValue::callbacks->read_memory(75        context, NULL, &symbolAddr, 1 * TValue::type_sizes.sizeof_long_long,76        &(tmpSize));77    if (ret != ompd_rc_ok)78      return ret;79    ret = TValue::callbacks->device_to_host(80        context, &tmpSize, TValue::type_sizes.sizeof_long_long, 1, &(typeSize));81  }82  *size = typeSize;83  return ret;84}85 86ompd_rc_t TType::getBitfieldMask(const char *fieldName,87                                 uint64_t *bitfieldmask) {88  ompd_rc_t ret = ompd_rc_ok;89  auto i = bitfieldMasks.find(fieldName);90  if (i == bitfieldMasks.end()) {91    uint64_t tmpMask, bitfieldMask;92    ompd_address_t symbolAddr;93    std::stringstream ss;94    ss << "ompd_bitfield__" << typeName << "__" << fieldName;95    ret = TValue::callbacks->symbol_addr_lookup(context, NULL, ss.str().c_str(),96                                                &symbolAddr, NULL);97    if (ret != ompd_rc_ok) {98      dout << "missing symbol " << ss.str()99           << " add this to ompd-specific.h:\nOMPD_BITFIELD(" << typeName << ","100           << fieldName << ") \\" << std::endl;101      return ret;102    }103    symbolAddr.segment = descSegment;104 105    ret = TValue::callbacks->read_memory(106        context, NULL, &symbolAddr, 1 * TValue::type_sizes.sizeof_long_long,107        &(tmpMask));108    if (ret != ompd_rc_ok)109      return ret;110    ret = TValue::callbacks->device_to_host(context, &(tmpMask),111                                            TValue::type_sizes.sizeof_long_long,112                                            1, &(bitfieldMask));113    if (ret != ompd_rc_ok) {114      return ret;115    }116    i = bitfieldMasks.insert(i, std::make_pair(fieldName, bitfieldMask));117  }118  *bitfieldmask = i->second;119  return ret;120}121 122ompd_rc_t TType::getElementOffset(const char *fieldName, ompd_size_t *offset) {123  ompd_rc_t ret = ompd_rc_ok;124  auto i = fieldOffsets.find(fieldName);125  if (i == fieldOffsets.end()) {126    ompd_size_t tmpOffset, fieldOffset;127    ompd_address_t symbolAddr;128    std::stringstream ss;129    ss << "ompd_access__" << typeName << "__" << fieldName;130 131    ret = TValue::callbacks->symbol_addr_lookup(context, NULL, ss.str().c_str(),132                                                &symbolAddr, NULL);133    if (ret != ompd_rc_ok) {134      dout << "missing symbol " << ss.str()135           << " add this to ompd-specific.h:\nOMPD_ACCESS(" << typeName << ","136           << fieldName << ") \\" << std::endl;137      return ret;138    }139    symbolAddr.segment = descSegment;140 141    ret = TValue::callbacks->read_memory(142        context, NULL, &symbolAddr, 1 * TValue::type_sizes.sizeof_long_long,143        &(tmpOffset));144    if (ret != ompd_rc_ok)145      return ret;146    ret = TValue::callbacks->device_to_host(context, &(tmpOffset),147                                            TValue::type_sizes.sizeof_long_long,148                                            1, &fieldOffset);149    if (ret != ompd_rc_ok) {150      return ret;151    }152    i = fieldOffsets.insert(i, std::make_pair(fieldName, fieldOffset));153  }154  *offset = i->second;155  return ret;156}157 158ompd_rc_t TType::getElementSize(const char *fieldName, ompd_size_t *size) {159  ompd_rc_t ret = ompd_rc_ok;160  auto i = fieldSizes.find(fieldName);161  if (i == fieldSizes.end()) {162    ompd_size_t tmpOffset, fieldSize;163    ompd_address_t symbolAddr;164    std::stringstream ss;165    ss << "ompd_sizeof__" << typeName << "__" << fieldName;166 167    ret = TValue::callbacks->symbol_addr_lookup(context, NULL, ss.str().c_str(),168                                                &symbolAddr, NULL);169    if (ret != ompd_rc_ok) {170      dout << "missing symbol " << ss.str()171           << " add this to ompd-specific.h:\nOMPD_ACCESS(" << typeName << ","172           << fieldName << ") \\" << std::endl;173      return ret;174    }175    symbolAddr.segment = descSegment;176 177    ret = TValue::callbacks->read_memory(178        context, NULL, &symbolAddr, 1 * TValue::type_sizes.sizeof_long_long,179        &(tmpOffset));180    if (ret != ompd_rc_ok)181      return ret;182    ret = TValue::callbacks->device_to_host(context, &tmpOffset,183                                            TValue::type_sizes.sizeof_long_long,184                                            1, &fieldSize);185    if (ret != ompd_rc_ok) {186      return ret;187    }188    i = fieldSizes.insert(i, std::make_pair(fieldName, fieldSize));189  }190  *size = i->second;191  return ret;192}193 194TValue::TValue(ompd_address_space_context_t *_context,195               ompd_thread_context_t *_tcontext, const char *_valueName,196               ompd_addr_t segment)197    : errorState(ompd_rc_ok), type(&nullType), pointerLevel(0),198      context(_context), tcontext(_tcontext), fieldSize(0) {199  errorState.errorCode = callbacks->symbol_addr_lookup(200      context, tcontext, _valueName, &symbolAddr, NULL);201  symbolAddr.segment = segment;202}203 204TValue::TValue(ompd_address_space_context_t *_context,205               ompd_thread_context_t *_tcontext, ompd_address_t addr)206    : errorState(ompd_rc_ok), type(&nullType), pointerLevel(0),207      context(_context), tcontext(_tcontext), symbolAddr(addr), fieldSize(0) {208  if (addr.address == 0)209    errorState.errorCode = ompd_rc_bad_input;210}211 212TValue &TValue::cast(const char *typeName) {213  if (gotError())214    return *this;215  type = &tf.getType(context, typeName, symbolAddr.segment);216  pointerLevel = 0;217  assert(!type->isVoid() && "cast to invalid type failed");218  return *this;219}220 221TValue &TValue::cast(const char *typeName, int _pointerLevel,222                     ompd_addr_t segment) {223  if (gotError())224    return *this;225  type = &tf.getType(context, typeName, symbolAddr.segment);226  pointerLevel = _pointerLevel;227  symbolAddr.segment = segment;228  assert(!type->isVoid() && "cast to invalid type failed");229  return *this;230}231 232TValue TValue::dereference() const {233  if (gotError())234    return *this;235  ompd_address_t tmpAddr;236  assert(!type->isVoid() && "cannot work with void");237  assert(pointerLevel > 0 && "cannot dereference non-pointer");238  TValue ret = *this;239  ret.pointerLevel--;240  ret.errorState.errorCode = callbacks->read_memory(241      context, tcontext, &symbolAddr, 1 * TValue::type_sizes.sizeof_pointer,242      &(tmpAddr.address));243  if (ret.errorState.errorCode != ompd_rc_ok)244    return ret;245 246  ret.errorState.errorCode = callbacks->device_to_host(247      context, &(tmpAddr.address), TValue::type_sizes.sizeof_pointer, 1,248      &(ret.symbolAddr.address));249  if (ret.errorState.errorCode != ompd_rc_ok) {250    return ret;251  }252  if (ret.symbolAddr.address == 0)253    ret.errorState.errorCode = ompd_rc_unsupported;254  return ret;255}256 257ompd_rc_t TValue::getAddress(ompd_address_t *addr) const {258  *addr = symbolAddr;259  if (symbolAddr.address == 0)260    return ompd_rc_unsupported;261  return errorState.errorCode;262}263 264ompd_rc_t TValue::getRawValue(void *buf, int count) {265  if (errorState.errorCode != ompd_rc_ok)266    return errorState.errorCode;267  ompd_size_t size;268  errorState.errorCode = type->getSize(&size);269  if (errorState.errorCode != ompd_rc_ok)270    return errorState.errorCode;271 272  errorState.errorCode =273      callbacks->read_memory(context, tcontext, &symbolAddr, size, buf);274  return errorState.errorCode;275}276 277ompd_rc_t TValue::getString(const char **buf) {278  *buf = 0;279  if (gotError())280    return getError();281 282  TValue strValue = dereference();283  if (strValue.gotError()) {284    return strValue.getError();285  }286 287  if (!callbacks) {288    return ompd_rc_error;289  }290  ompd_rc_t ret;291#define BUF_LEN 512292  char *string_buffer;293 294  // Allocate an extra byte, but pass only BUF_LEN to the tool295  // so that we can detect truncation later.296  ret = callbacks->alloc_memory(BUF_LEN + 1, (void **)&string_buffer);297  if (ret != ompd_rc_ok) {298    return ret;299  }300  string_buffer[BUF_LEN] = '\0';301 302  // TODO: if we have not read in the complete string, we need to realloc303  // 'string_buffer' and attempt reading again repeatedly till the entire string304  // is read in.305  ret = callbacks->read_string(context, tcontext, &strValue.symbolAddr, BUF_LEN,306                               (void *)string_buffer);307  *buf = string_buffer;308  // Check for truncation. The standard specifies that if a null byte is not309  // among the first 'nbytes' bytes, the string placed in the buffer is not310  // null-terminated. 'nbytes' is BUF_LEN in this case.311  if (ret == ompd_rc_ok && strlen(string_buffer) == BUF_LEN) {312    return ompd_rc_error;313  }314  return ret;315}316 317TBaseValue TValue::castBase(const char *varName) {318  ompd_size_t size;319  errorState.errorCode =320      tf.getType(context, varName, symbolAddr.segment).getSize(&size);321  return TBaseValue(*this, size);322}323 324TBaseValue TValue::castBase() const {325  if (pointerLevel > 0)326    return TBaseValue(*this, type_sizes.sizeof_pointer);327  return TBaseValue(*this, fieldSize);328}329 330TBaseValue TValue::castBase(ompd_target_prim_types_t baseType) const {331  return TBaseValue(*this, baseType);332}333 334TValue TValue::access(const char *fieldName) const {335  if (gotError())336    return *this;337  TValue ret = *this;338  assert(pointerLevel < 2 && "access to field element of pointer array failed");339  if (pointerLevel == 1) // -> operator340    ret = ret.dereference();341  // we use *this for . operator342  ompd_size_t offset;343  ret.errorState.errorCode = type->getElementOffset(fieldName, &offset);344  ret.errorState.errorCode = type->getElementSize(fieldName, &(ret.fieldSize));345  ret.symbolAddr.address += offset;346 347  return ret;348}349 350ompd_rc_t TValue::check(const char *bitfieldName, ompd_word_t *isSet) const {351  if (gotError())352    return getError();353  int bitfield;354  uint64_t bitfieldmask;355  ompd_rc_t ret = this->castBase(ompd_type_int).getValue(&bitfield, 1);356  if (ret != ompd_rc_ok)357    return ret;358  ret = type->getBitfieldMask(bitfieldName, &bitfieldmask);359  *isSet = ((bitfield & bitfieldmask) != 0);360  return ret;361}362 363TValue TValue::getArrayElement(int elemNumber) const {364  if (gotError())365    return *this;366  TValue ret;367  if (pointerLevel > 0) {368    ret = dereference();369  } else {370    ret = *this;371  }372  if (ret.pointerLevel == 0) {373    ompd_size_t size;374    ret.errorState.errorCode = type->getSize(&size);375    ret.symbolAddr.address += elemNumber * size;376  } else {377    ret.symbolAddr.address += elemNumber * type_sizes.sizeof_pointer;378  }379  return ret;380}381 382TValue TValue::getPtrArrayElement(int elemNumber) const {383  if (gotError()) {384    return *this;385  }386  assert(pointerLevel > 0 && "This only works on arrays of pointers");387  TValue ret = *this;388  ret.symbolAddr.address += elemNumber * type_sizes.sizeof_pointer;389  return ret;390}391 392TBaseValue::TBaseValue(const TValue &_tvalue,393                       ompd_target_prim_types_t _baseType)394    : TValue(_tvalue), baseTypeSize(ompd_sizeof(_baseType)) {}395TBaseValue::TBaseValue(const TValue &_tvalue, ompd_size_t _baseTypeSize)396    : TValue(_tvalue), baseTypeSize(_baseTypeSize) {}397 398ompd_rc_t TBaseValue::getValue(void *buf, int count) {399  if (errorState.errorCode != ompd_rc_ok)400    return errorState.errorCode;401  errorState.errorCode = callbacks->read_memory(context, tcontext, &symbolAddr,402                                                count * baseTypeSize, buf);403  if (errorState.errorCode != ompd_rc_ok)404    return errorState.errorCode;405  errorState.errorCode =406      callbacks->device_to_host(context, buf, baseTypeSize, count, buf);407  return errorState.errorCode;408}409