1 /*
2 * TargetValue.h -- Access to target values using OMPD callbacks
3 */
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-exception
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "omp-tools.h"
14 #include "ompd-private.h"
15 #include <stdlib.h>
16
17 #ifndef SRC_TARGET_VALUE_H_
18 #define SRC_TARGET_VALUE_H_
19
20 #ifdef __cplusplus
21
22 #include <cassert>
23 #include <map>
24 #include <string>
25
26 class TType;
27 class TValue;
28 class TBaseValue;
29
30 class TTypeFactory {
31 protected:
32 std::map<ompd_address_space_context_t *, std::map<const char *, TType>>
33 ttypes;
34
35 public:
TTypeFactory()36 TTypeFactory() : ttypes() {}
37 TType &getType(ompd_address_space_context_t *context, const char *typName,
38 ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED);
39 };
40
41 static thread_local TTypeFactory tf = TTypeFactory();
42
43 class TType {
44 protected:
45 ompd_size_t typeSize;
46 std::map<const char *, ompd_size_t> fieldOffsets;
47 std::map<const char *, ompd_size_t> fieldSizes;
48 std::map<const char *, uint64_t> bitfieldMasks;
49 ompd_addr_t descSegment;
50 const char *typeName;
51 ompd_address_space_context_t *context;
52 bool isvoid;
53 TType(ompd_address_space_context_t *context, const char *typeName,
54 ompd_addr_t _segment = OMPD_SEGMENT_UNSPECIFIED);
55
56 public:
57 TType(bool, ompd_addr_t _segment = OMPD_SEGMENT_UNSPECIFIED)
descSegment(_segment)58 : descSegment(_segment), isvoid(true) {}
isVoid()59 bool isVoid() const { return isvoid; }
60 ompd_rc_t getElementOffset(const char *fieldName, ompd_size_t *offset);
61 ompd_rc_t getElementSize(const char *fieldName, ompd_size_t *size);
62 ompd_rc_t getBitfieldMask(const char *fieldName, uint64_t *bitfieldmask);
63 ompd_rc_t getSize(ompd_size_t *size);
64 friend TValue;
65 friend TTypeFactory;
66 };
67
68 static TType nullType(true);
69
70 /**
71 * class TError
72 * As TValue is designed to concatenate operations, we use TError
73 * to catch errors that might happen on each operation and provide
74 * the according error code and which operation raised the error.
75 */
76
77 class TError {
78 protected:
79 ompd_rc_t errorCode;
TError()80 TError() : errorCode(ompd_rc_ok) {}
TError(const ompd_rc_t & error)81 TError(const ompd_rc_t &error) : errorCode(error) {}
82
83 public:
toString()84 std::string toString() {
85 return std::string("TError messages not implemented yet");
86 }
87 friend TValue;
88 friend TBaseValue;
89 };
90
91 /**
92 * class TValue
93 * This class encapsules the access to target values by using OMPD
94 * callback functions. The member functions are designed to concatenate
95 * the operations that are needed to access values from structures
96 * e.g., _a[6]->_b._c would read like :
97 * TValue(ctx,
98 * "_a").cast("A",2).getArrayElement(6).access("_b").cast("B").access("_c")
99 */
100
101 class TValue {
102 protected:
103 TError errorState;
104 TType *type;
105 int pointerLevel;
106 ompd_address_space_context_t *context;
107 ompd_thread_context_t *tcontext;
108 ompd_address_t symbolAddr;
109 ompd_size_t fieldSize;
110
111 public:
112 static const ompd_callbacks_t *callbacks;
113 static ompd_device_type_sizes_t type_sizes;
114
TValue()115 TValue() : errorState(ompd_rc_error) {}
116 /**
117 * Create a target value object from symbol name
118 */
119 TValue(ompd_address_space_context_t *_context, const char *_valueName,
120 ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED)
TValue(_context,NULL,_valueName,segment)121 : TValue(_context, NULL, _valueName, segment) {}
122
123 TValue(ompd_address_space_context_t *context, ompd_thread_context_t *tcontext,
124 const char *valueName, ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED);
125 /**
126 * Create a target value object from target value address
127 */
TValue(ompd_address_space_context_t * _context,ompd_address_t _addr)128 TValue(ompd_address_space_context_t *_context, ompd_address_t _addr)
129 : TValue(_context, NULL, _addr) {}
130 TValue(ompd_address_space_context_t *context, ompd_thread_context_t *tcontext,
131 ompd_address_t addr);
132 /**
133 * Cast the target value object to some type of typeName
134 *
135 * This call modifies the object and returns a reference to the modified
136 * object
137 */
138 TValue &cast(const char *typeName);
139
140 /**
141 * Cast the target value object to some pointer of type typename
142 * pointerlevel gives the number of *
143 * e.g., char** would be: cast("char",2)
144 *
145 * This call modifies the object and returns a reference to the modified
146 * object
147 */
148 TValue &cast(const char *typeName, int pointerLevel,
149 ompd_addr_t segment = OMPD_SEGMENT_UNSPECIFIED);
150
151 /**
152 * Get the target address of the target value
153 */
154 ompd_rc_t getAddress(ompd_address_t *addr) const;
155 /**
156 * Get the raw memory copy of the target value
157 */
158 ompd_rc_t getRawValue(void *buf, int count);
159 /**
160 * Fetch a string copy from the target. "this" represents the pointer
161 * that holds the value of a null terminated character string. "buf"
162 * points to the destination string to be allocated and copied to.
163 * Returns 'ompd_rc_error' to signify a truncated string or a target
164 * read error.
165 */
166 ompd_rc_t getString(const char **buf);
167 /**
168 * Get a new target value object for the dereferenced target value
169 * reduces the pointer level, uses the target value as new target address,
170 * keeps the target type
171 */
172 TValue dereference() const;
173 /**
174 * Cast to a base type
175 * Only values of base type may be read from target
176 */
177 TBaseValue castBase(ompd_target_prim_types_t baseType) const;
178 /**
179 * Cast to a base type
180 * Get the size by fieldsize from runtime
181 */
182 TBaseValue castBase() const;
183 /**
184 * Cast to a base type
185 * Get the size by name from the rtl
186 */
187 TBaseValue castBase(const char *varName);
188 /**
189 * Resolve field access for structs/unions
190 * this supports both "->" and "." operator.
191 */
192 TValue access(const char *fieldName) const;
193 /**
194 * Tests for a field bit in a bitfield
195 */
196 ompd_rc_t check(const char *bitfieldName, ompd_word_t *isSet) const;
197 /**
198 * Get an array element
199 */
200 TValue getArrayElement(int elemNumber) const;
201 /**
202 * Get an element of a pointer array
203 */
204 TValue getPtrArrayElement(int elemNumber) const;
205 /**
206 * Did we raise some error yet?
207 */
gotError()208 bool gotError() const { return errorState.errorCode != ompd_rc_ok; }
209 /**
210 * Get the error code
211 */
getError()212 ompd_rc_t getError() const { return errorState.errorCode; }
213 /**
214 * Did we raise some error yet?
215 */
getErrorMessage()216 std::string getErrorMessage() { return errorState.toString(); }
217 };
218
219 class TBaseValue : public TValue {
220 protected:
221 ompd_size_t baseTypeSize = 0;
222 TBaseValue(const TValue &, ompd_target_prim_types_t baseType);
223 TBaseValue(const TValue &, ompd_size_t baseTypeSize);
224
225 public:
226 ompd_rc_t getValue(void *buf, int count);
227 template <typename T> ompd_rc_t getValue(T &buf);
228
229 friend TValue;
230 };
231
getValue(T & buf)232 template <typename T> ompd_rc_t TBaseValue::getValue(T &buf) {
233 assert(sizeof(T) >= baseTypeSize);
234 if (sizeof(T) == baseTypeSize)
235 return getValue(&buf, 1);
236
237 char tmp[sizeof(T)];
238 ompd_rc_t ret = getValue(tmp, 1);
239 switch (baseTypeSize) {
240 case 1:
241 buf = (T) * ((int8_t *)tmp);
242 break;
243 case 2:
244 buf = (T) * ((int16_t *)tmp);
245 break;
246 case 4:
247 buf = (T) * ((int32_t *)tmp);
248 break;
249 case 8:
250 buf = (T) * ((int64_t *)tmp);
251 break;
252 default:
253 assert(0 && "Invalid baseTypeSize");
254 break;
255 }
256 return ret;
257 }
258
259 #define EXTERN_C extern "C"
260 #else
261 #define EXTERN_C
262 #endif
263
264 #endif /*SRC_TARGET_VALUE_H_*/
265