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