Commit | Line | Data |
---|---|---|
980c17b1 MD |
1 | // SPDX-License-Identifier: MIT |
2 | /* | |
3 | * Copyright 2022-2024 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
4 | */ | |
5 | ||
6 | #include <string.h> | |
7 | ||
8 | #include "visit-arg-vec.h" | |
9 | ||
10 | union int_value { | |
11 | uint64_t u[NR_SIDE_INTEGER128_SPLIT]; | |
12 | int64_t s[NR_SIDE_INTEGER128_SPLIT]; | |
13 | }; | |
14 | ||
15 | static | |
16 | void visit_dynamic_type(const struct side_type_visitor *type_visitor, const struct side_arg *dynamic_item, void *priv); | |
17 | ||
18 | static | |
19 | void visit_dynamic_elem(const struct side_type_visitor *type_visitor, const struct side_arg *dynamic_item, void *priv); | |
20 | ||
21 | static | |
22 | uint32_t visit_gather_type(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const void *ptr, void *priv); | |
23 | ||
24 | static | |
25 | uint32_t visit_gather_elem(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const void *ptr, void *priv); | |
26 | ||
27 | static | |
28 | void side_visit_type(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const struct side_arg *item, void *priv); | |
29 | ||
30 | static | |
31 | void side_visit_elem(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const struct side_arg *item, void *priv); | |
32 | ||
33 | static | |
34 | uint32_t type_visitor_gather_enum(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, void *priv); | |
35 | ||
36 | static | |
37 | uint32_t type_visitor_gather_struct(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, void *priv); | |
38 | ||
39 | static | |
40 | uint32_t type_visitor_gather_array(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, void *priv); | |
41 | ||
42 | static | |
43 | uint32_t type_visitor_gather_vla(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, | |
44 | const void *_length_ptr, void *priv); | |
45 | ||
46 | static | |
47 | union int_value tracer_load_integer_value(const struct side_type_integer *type_integer, | |
48 | const union side_integer_value *value, | |
49 | uint16_t offset_bits, uint16_t *_len_bits) | |
50 | { | |
51 | union int_value v = {}; | |
52 | uint16_t len_bits; | |
53 | bool reverse_bo; | |
54 | ||
55 | if (!type_integer->len_bits) | |
56 | len_bits = type_integer->integer_size * CHAR_BIT; | |
57 | else | |
58 | len_bits = type_integer->len_bits; | |
59 | if (len_bits + offset_bits > type_integer->integer_size * CHAR_BIT) | |
60 | abort(); | |
61 | reverse_bo = side_enum_get(type_integer->byte_order) != SIDE_TYPE_BYTE_ORDER_HOST; | |
62 | switch (type_integer->integer_size) { | |
63 | case 1: | |
64 | if (type_integer->signedness) | |
65 | v.s[SIDE_INTEGER128_SPLIT_LOW] = value->side_s8; | |
66 | else | |
67 | v.u[SIDE_INTEGER128_SPLIT_LOW] = value->side_u8; | |
68 | break; | |
69 | case 2: | |
70 | if (type_integer->signedness) { | |
71 | int16_t side_s16; | |
72 | ||
73 | side_s16 = value->side_s16; | |
74 | if (reverse_bo) | |
75 | side_s16 = side_bswap_16(side_s16); | |
76 | v.s[SIDE_INTEGER128_SPLIT_LOW] = side_s16; | |
77 | } else { | |
78 | uint16_t side_u16; | |
79 | ||
80 | side_u16 = value->side_u16; | |
81 | if (reverse_bo) | |
82 | side_u16 = side_bswap_16(side_u16); | |
83 | v.u[SIDE_INTEGER128_SPLIT_LOW] = side_u16; | |
84 | } | |
85 | break; | |
86 | case 4: | |
87 | if (type_integer->signedness) { | |
88 | int32_t side_s32; | |
89 | ||
90 | side_s32 = value->side_s32; | |
91 | if (reverse_bo) | |
92 | side_s32 = side_bswap_32(side_s32); | |
93 | v.s[SIDE_INTEGER128_SPLIT_LOW] = side_s32; | |
94 | } else { | |
95 | uint32_t side_u32; | |
96 | ||
97 | side_u32 = value->side_u32; | |
98 | if (reverse_bo) | |
99 | side_u32 = side_bswap_32(side_u32); | |
100 | v.u[SIDE_INTEGER128_SPLIT_LOW] = side_u32; | |
101 | } | |
102 | break; | |
103 | case 8: | |
104 | if (type_integer->signedness) { | |
105 | int64_t side_s64; | |
106 | ||
107 | side_s64 = value->side_s64; | |
108 | if (reverse_bo) | |
109 | side_s64 = side_bswap_64(side_s64); | |
110 | v.s[SIDE_INTEGER128_SPLIT_LOW] = side_s64; | |
111 | } else { | |
112 | uint64_t side_u64; | |
113 | ||
114 | side_u64 = value->side_u64; | |
115 | if (reverse_bo) | |
116 | side_u64 = side_bswap_64(side_u64); | |
117 | v.u[SIDE_INTEGER128_SPLIT_LOW] = side_u64; | |
118 | } | |
119 | break; | |
120 | case 16: | |
121 | if (type_integer->signedness) { | |
122 | int64_t side_s64[NR_SIDE_INTEGER128_SPLIT]; | |
123 | ||
124 | side_s64[SIDE_INTEGER128_SPLIT_LOW] = value->side_s128_split[SIDE_INTEGER128_SPLIT_LOW]; | |
125 | side_s64[SIDE_INTEGER128_SPLIT_HIGH] = value->side_s128_split[SIDE_INTEGER128_SPLIT_HIGH]; | |
126 | if (reverse_bo) { | |
127 | side_s64[SIDE_INTEGER128_SPLIT_LOW] = side_bswap_64(side_s64[SIDE_INTEGER128_SPLIT_LOW]); | |
128 | side_s64[SIDE_INTEGER128_SPLIT_HIGH] = side_bswap_64(side_s64[SIDE_INTEGER128_SPLIT_HIGH]); | |
129 | v.s[SIDE_INTEGER128_SPLIT_LOW] = side_s64[SIDE_INTEGER128_SPLIT_HIGH]; | |
130 | v.s[SIDE_INTEGER128_SPLIT_HIGH] = side_s64[SIDE_INTEGER128_SPLIT_LOW]; | |
131 | } else { | |
132 | v.s[SIDE_INTEGER128_SPLIT_LOW] = side_s64[SIDE_INTEGER128_SPLIT_LOW]; | |
133 | v.s[SIDE_INTEGER128_SPLIT_HIGH] = side_s64[SIDE_INTEGER128_SPLIT_HIGH]; | |
134 | } | |
135 | } else { | |
136 | uint64_t side_u64[NR_SIDE_INTEGER128_SPLIT]; | |
137 | ||
138 | side_u64[SIDE_INTEGER128_SPLIT_LOW] = value->side_u128_split[SIDE_INTEGER128_SPLIT_LOW]; | |
139 | side_u64[SIDE_INTEGER128_SPLIT_HIGH] = value->side_u128_split[SIDE_INTEGER128_SPLIT_HIGH]; | |
140 | if (reverse_bo) { | |
141 | side_u64[SIDE_INTEGER128_SPLIT_LOW] = side_bswap_64(side_u64[SIDE_INTEGER128_SPLIT_LOW]); | |
142 | side_u64[SIDE_INTEGER128_SPLIT_HIGH] = side_bswap_64(side_u64[SIDE_INTEGER128_SPLIT_HIGH]); | |
143 | v.u[SIDE_INTEGER128_SPLIT_LOW] = side_u64[SIDE_INTEGER128_SPLIT_HIGH]; | |
144 | v.u[SIDE_INTEGER128_SPLIT_HIGH] = side_u64[SIDE_INTEGER128_SPLIT_LOW]; | |
145 | } else { | |
146 | v.u[SIDE_INTEGER128_SPLIT_LOW] = side_u64[SIDE_INTEGER128_SPLIT_LOW]; | |
147 | v.u[SIDE_INTEGER128_SPLIT_HIGH] = side_u64[SIDE_INTEGER128_SPLIT_HIGH]; | |
148 | } | |
149 | } | |
150 | break; | |
151 | default: | |
152 | abort(); | |
153 | } | |
154 | if (type_integer->integer_size <= 8) { | |
155 | v.u[SIDE_INTEGER128_SPLIT_LOW] >>= offset_bits; | |
156 | if (len_bits < 64) { | |
157 | v.u[SIDE_INTEGER128_SPLIT_LOW] &= (1ULL << len_bits) - 1; | |
158 | if (type_integer->signedness) { | |
159 | /* Sign-extend. */ | |
160 | if (v.u[SIDE_INTEGER128_SPLIT_LOW] & (1ULL << (len_bits - 1))) { | |
161 | v.u[SIDE_INTEGER128_SPLIT_LOW] |= ~((1ULL << len_bits) - 1); | |
162 | v.u[SIDE_INTEGER128_SPLIT_HIGH] = ~0ULL; | |
163 | } | |
164 | } | |
165 | } | |
166 | } else { | |
167 | //TODO: Implement 128-bit integer with len_bits != 128 or nonzero offset_bits | |
168 | if (len_bits < 128 || offset_bits != 0) | |
169 | abort(); | |
170 | } | |
171 | if (_len_bits) | |
172 | *_len_bits = len_bits; | |
173 | return v; | |
174 | } | |
175 | ||
176 | static | |
177 | void side_check_value_u64(union int_value v) | |
178 | { | |
179 | if (v.u[SIDE_INTEGER128_SPLIT_HIGH]) { | |
180 | fprintf(stderr, "Unexpected integer value\n"); | |
181 | abort(); | |
182 | } | |
183 | } | |
184 | ||
185 | /* | |
186 | * return the size of the input string including the null terminator, in | |
187 | * bytes. | |
188 | */ | |
189 | static | |
190 | size_t type_visitor_strlen(const void *p, uint8_t unit_size) | |
191 | { | |
192 | size_t inbytesleft = 0; | |
193 | ||
194 | switch (unit_size) { | |
195 | case 1: | |
196 | { | |
197 | const char *str = p; | |
198 | ||
199 | return strlen(str) + 1; | |
200 | } | |
201 | case 2: | |
202 | { | |
203 | const uint16_t *p16 = p; | |
204 | ||
205 | for (; *p16; p16++) | |
206 | inbytesleft += 2; | |
207 | return inbytesleft + 2; /* Include 2-byte null terminator. */ | |
208 | } | |
209 | case 4: | |
210 | { | |
211 | const uint32_t *p32 = p; | |
212 | ||
213 | for (; *p32; p32++) | |
214 | inbytesleft += 4; | |
215 | return inbytesleft + 4; /* Include 4-byte null terminator. */ | |
216 | } | |
217 | default: | |
218 | fprintf(stderr, "Unknown string unit size %" PRIu8 "\n", unit_size); | |
219 | abort(); | |
220 | } | |
221 | } | |
222 | ||
223 | static | |
224 | void side_visit_elem(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const struct side_arg *item, void *priv) | |
225 | { | |
226 | if (type_visitor->elem_func) | |
227 | type_visitor->elem_func(SIDE_TYPE_VISITOR_BEFORE, type_desc, priv); | |
228 | side_visit_type(type_visitor, type_desc, item, priv); | |
229 | if (type_visitor->elem_func) | |
230 | type_visitor->elem_func(SIDE_TYPE_VISITOR_AFTER, type_desc, priv); | |
231 | } | |
232 | ||
233 | static | |
234 | void side_visit_field(const struct side_type_visitor *type_visitor, const struct side_event_field *item_desc, const struct side_arg *item, void *priv) | |
235 | { | |
236 | if (type_visitor->field_func) | |
237 | type_visitor->field_func(SIDE_TYPE_VISITOR_BEFORE, item_desc, priv); | |
238 | side_visit_type(type_visitor, &item_desc->side_type, item, priv); | |
239 | if (type_visitor->field_func) | |
240 | type_visitor->field_func(SIDE_TYPE_VISITOR_AFTER, item_desc, priv); | |
241 | } | |
242 | ||
243 | static | |
244 | void type_visitor_struct(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec, void *priv) | |
245 | { | |
246 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); | |
247 | const struct side_type_struct *side_struct = side_ptr_get(type_desc->u.side_struct); | |
248 | uint32_t i, side_sav_len = side_arg_vec->len; | |
249 | ||
250 | if (side_struct->nr_fields != side_sav_len) { | |
251 | fprintf(stderr, "ERROR: number of fields mismatch between description and arguments of structure\n"); | |
252 | abort(); | |
253 | } | |
254 | if (type_visitor->struct_type_func) | |
255 | type_visitor->struct_type_func(SIDE_TYPE_VISITOR_BEFORE, side_struct, side_arg_vec, priv); | |
256 | for (i = 0; i < side_sav_len; i++) | |
257 | side_visit_field(type_visitor, &side_ptr_get(side_struct->fields)[i], &sav[i], priv); | |
258 | if (type_visitor->struct_type_func) | |
259 | type_visitor->struct_type_func(SIDE_TYPE_VISITOR_AFTER, side_struct, side_arg_vec, priv); | |
260 | } | |
261 | ||
262 | static | |
263 | void type_visitor_variant(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const struct side_arg_variant *side_arg_variant, void *priv) | |
264 | { | |
265 | const struct side_type_variant *side_type_variant = side_ptr_get(type_desc->u.side_variant); | |
266 | const struct side_type *selector_type = &side_type_variant->selector; | |
267 | union int_value v; | |
268 | uint32_t i; | |
269 | ||
270 | if (side_enum_get(selector_type->type) != side_enum_get(side_arg_variant->selector.type)) { | |
271 | fprintf(stderr, "ERROR: Unexpected variant selector type\n"); | |
272 | abort(); | |
273 | } | |
274 | switch (side_enum_get(selector_type->type)) { | |
275 | case SIDE_TYPE_U8: | |
276 | case SIDE_TYPE_U16: | |
277 | case SIDE_TYPE_U32: | |
278 | case SIDE_TYPE_U64: | |
279 | case SIDE_TYPE_U128: | |
280 | case SIDE_TYPE_S8: | |
281 | case SIDE_TYPE_S16: | |
282 | case SIDE_TYPE_S32: | |
283 | case SIDE_TYPE_S64: | |
284 | case SIDE_TYPE_S128: | |
285 | break; | |
286 | default: | |
287 | fprintf(stderr, "ERROR: Expecting integer variant selector type\n"); | |
288 | abort(); | |
289 | } | |
290 | v = tracer_load_integer_value(&selector_type->u.side_integer, | |
291 | &side_arg_variant->selector.u.side_static.integer_value, 0, NULL); | |
292 | side_check_value_u64(v); | |
293 | for (i = 0; i < side_type_variant->nr_options; i++) { | |
294 | const struct side_variant_option *option = &side_ptr_get(side_type_variant->options)[i]; | |
295 | ||
296 | if (v.s[SIDE_INTEGER128_SPLIT_LOW] >= option->range_begin && v.s[SIDE_INTEGER128_SPLIT_LOW] <= option->range_end) { | |
297 | side_visit_type(type_visitor, &option->side_type, &side_arg_variant->option, priv); | |
298 | return; | |
299 | } | |
300 | } | |
301 | fprintf(stderr, "ERROR: Variant selector value unknown %" PRId64 "\n", v.s[SIDE_INTEGER128_SPLIT_LOW]); | |
302 | abort(); | |
303 | } | |
304 | ||
305 | static | |
306 | void type_visitor_array(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec, void *priv) | |
307 | { | |
308 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); | |
309 | uint32_t i, side_sav_len = side_arg_vec->len; | |
310 | ||
311 | if (type_desc->u.side_array.length != side_sav_len) { | |
312 | fprintf(stderr, "ERROR: length mismatch between description and arguments of array\n"); | |
313 | abort(); | |
314 | } | |
315 | if (type_visitor->array_type_func) | |
316 | type_visitor->array_type_func(SIDE_TYPE_VISITOR_BEFORE, &type_desc->u.side_array, side_arg_vec, priv); | |
317 | for (i = 0; i < side_sav_len; i++) | |
318 | side_visit_elem(type_visitor, side_ptr_get(type_desc->u.side_array.elem_type), &sav[i], priv); | |
319 | if (type_visitor->array_type_func) | |
320 | type_visitor->array_type_func(SIDE_TYPE_VISITOR_AFTER, &type_desc->u.side_array, side_arg_vec, priv); | |
321 | } | |
322 | ||
323 | static | |
324 | void type_visitor_vla(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec, void *priv) | |
325 | { | |
326 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); | |
327 | uint32_t i, side_sav_len = side_arg_vec->len; | |
328 | ||
329 | if (type_visitor->vla_type_func) | |
330 | type_visitor->vla_type_func(SIDE_TYPE_VISITOR_BEFORE, &type_desc->u.side_vla, side_arg_vec, priv); | |
331 | for (i = 0; i < side_sav_len; i++) | |
332 | side_visit_elem(type_visitor, side_ptr_get(type_desc->u.side_vla.elem_type), &sav[i], priv); | |
333 | if (type_visitor->vla_type_func) | |
334 | type_visitor->vla_type_func(SIDE_TYPE_VISITOR_AFTER, &type_desc->u.side_vla, side_arg_vec, priv); | |
335 | } | |
336 | ||
337 | struct tracer_visitor_priv { | |
338 | const struct side_type_visitor *type_visitor; | |
339 | void *priv; | |
340 | const struct side_type *elem_type; | |
341 | int i; | |
342 | }; | |
343 | ||
344 | static | |
345 | enum side_visitor_status tracer_write_elem_cb(const struct side_tracer_visitor_ctx *tracer_ctx, | |
346 | const struct side_arg *elem) | |
347 | { | |
348 | struct tracer_visitor_priv *tracer_priv = (struct tracer_visitor_priv *) tracer_ctx->priv; | |
349 | ||
350 | side_visit_elem(tracer_priv->type_visitor, tracer_priv->elem_type, elem, tracer_priv->priv); | |
351 | return SIDE_VISITOR_STATUS_OK; | |
352 | } | |
353 | ||
354 | static | |
355 | void type_visitor_vla_visitor(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, struct side_arg_vla_visitor *vla_visitor, void *priv) | |
356 | { | |
357 | struct tracer_visitor_priv tracer_priv = { | |
358 | .type_visitor = type_visitor, | |
359 | .priv = priv, | |
f0619c77 | 360 | .elem_type = side_ptr_get(side_ptr_get(type_desc->u.side_vla_visitor)->elem_type), |
980c17b1 MD |
361 | .i = 0, |
362 | }; | |
363 | const struct side_tracer_visitor_ctx tracer_ctx = { | |
364 | .write_elem = tracer_write_elem_cb, | |
365 | .priv = &tracer_priv, | |
366 | }; | |
367 | enum side_visitor_status status; | |
368 | side_visitor_func func; | |
369 | void *app_ctx; | |
370 | ||
371 | if (!vla_visitor) | |
372 | abort(); | |
373 | if (type_visitor->vla_visitor_type_func) | |
f0619c77 | 374 | type_visitor->vla_visitor_type_func(SIDE_TYPE_VISITOR_BEFORE, side_ptr_get(type_desc->u.side_vla_visitor), vla_visitor, priv); |
980c17b1 | 375 | app_ctx = side_ptr_get(vla_visitor->app_ctx); |
f0619c77 | 376 | func = side_ptr_get(side_ptr_get(type_desc->u.side_vla_visitor)->visitor); |
980c17b1 MD |
377 | status = func(&tracer_ctx, app_ctx); |
378 | switch (status) { | |
379 | case SIDE_VISITOR_STATUS_OK: | |
380 | break; | |
381 | case SIDE_VISITOR_STATUS_ERROR: | |
382 | fprintf(stderr, "ERROR: Visitor error\n"); | |
383 | abort(); | |
384 | } | |
385 | if (type_visitor->vla_visitor_type_func) | |
f0619c77 | 386 | type_visitor->vla_visitor_type_func(SIDE_TYPE_VISITOR_AFTER, side_ptr_get(type_desc->u.side_vla_visitor), vla_visitor, priv); |
980c17b1 MD |
387 | } |
388 | ||
389 | static | |
390 | const char *tracer_gather_access(enum side_type_gather_access_mode access_mode, const char *ptr) | |
391 | { | |
392 | switch (access_mode) { | |
393 | case SIDE_TYPE_GATHER_ACCESS_DIRECT: | |
394 | return ptr; | |
395 | case SIDE_TYPE_GATHER_ACCESS_POINTER: | |
396 | /* Dereference pointer */ | |
397 | memcpy(&ptr, ptr, sizeof(const char *)); | |
398 | return ptr; | |
399 | default: | |
400 | abort(); | |
401 | } | |
402 | } | |
403 | ||
404 | static | |
405 | uint32_t tracer_gather_size(enum side_type_gather_access_mode access_mode, uint32_t len) | |
406 | { | |
407 | switch (access_mode) { | |
408 | case SIDE_TYPE_GATHER_ACCESS_DIRECT: | |
409 | return len; | |
410 | case SIDE_TYPE_GATHER_ACCESS_POINTER: | |
411 | return sizeof(void *); | |
412 | default: | |
413 | abort(); | |
414 | } | |
415 | } | |
416 | ||
417 | static | |
418 | union int_value tracer_load_gather_integer_value(const struct side_type_gather_integer *side_integer, | |
419 | const void *_ptr) | |
420 | { | |
f0619c77 | 421 | enum side_type_gather_access_mode access_mode = side_enum_get(side_integer->access_mode); |
980c17b1 MD |
422 | uint32_t integer_size_bytes = side_integer->type.integer_size; |
423 | const char *ptr = (const char *) _ptr; | |
424 | union side_integer_value value; | |
425 | ||
426 | ptr = tracer_gather_access(access_mode, ptr + side_integer->offset); | |
427 | memcpy(&value, ptr, integer_size_bytes); | |
428 | return tracer_load_integer_value(&side_integer->type, &value, | |
429 | side_integer->offset_bits, NULL); | |
430 | } | |
431 | ||
432 | static | |
433 | void visit_gather_field(const struct side_type_visitor *type_visitor, const struct side_event_field *field, const void *ptr, void *priv) | |
434 | { | |
435 | if (type_visitor->field_func) | |
436 | type_visitor->field_func(SIDE_TYPE_VISITOR_BEFORE, field, priv); | |
437 | (void) visit_gather_type(type_visitor, &field->side_type, ptr, priv); | |
438 | if (type_visitor->field_func) | |
439 | type_visitor->field_func(SIDE_TYPE_VISITOR_AFTER, field, priv); | |
440 | } | |
441 | ||
442 | static | |
443 | uint32_t type_visitor_gather_struct(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, void *priv) | |
444 | { | |
f0619c77 | 445 | enum side_type_gather_access_mode access_mode = side_enum_get(type_gather->u.side_struct.access_mode); |
980c17b1 MD |
446 | const struct side_type_struct *side_struct = side_ptr_get(type_gather->u.side_struct.type); |
447 | const char *ptr = (const char *) _ptr; | |
448 | uint32_t i; | |
449 | ||
450 | if (type_visitor->gather_struct_type_func) | |
451 | type_visitor->gather_struct_type_func(SIDE_TYPE_VISITOR_BEFORE, side_struct, priv); | |
452 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_struct.offset); | |
453 | for (i = 0; i < side_struct->nr_fields; i++) | |
454 | visit_gather_field(type_visitor, &side_ptr_get(side_struct->fields)[i], ptr, priv); | |
455 | if (type_visitor->gather_struct_type_func) | |
456 | type_visitor->gather_struct_type_func(SIDE_TYPE_VISITOR_AFTER, side_struct, priv); | |
457 | return tracer_gather_size(access_mode, type_gather->u.side_struct.size); | |
458 | } | |
459 | ||
460 | static | |
461 | uint32_t type_visitor_gather_array(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, void *priv) | |
462 | { | |
f0619c77 | 463 | enum side_type_gather_access_mode access_mode = side_enum_get(type_gather->u.side_array.access_mode); |
980c17b1 MD |
464 | const struct side_type_array *side_array = &type_gather->u.side_array.type; |
465 | const char *ptr = (const char *) _ptr, *orig_ptr; | |
466 | uint32_t i; | |
467 | ||
468 | if (type_visitor->gather_array_type_func) | |
469 | type_visitor->gather_array_type_func(SIDE_TYPE_VISITOR_BEFORE, side_array, priv); | |
470 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_array.offset); | |
471 | orig_ptr = ptr; | |
472 | for (i = 0; i < side_array->length; i++) { | |
473 | const struct side_type *elem_type = side_ptr_get(side_array->elem_type); | |
474 | ||
475 | switch (side_enum_get(elem_type->type)) { | |
476 | case SIDE_TYPE_GATHER_VLA: | |
477 | fprintf(stderr, "<gather VLA only supported within gather structures>\n"); | |
478 | abort(); | |
479 | default: | |
480 | break; | |
481 | } | |
482 | ptr += visit_gather_elem(type_visitor, elem_type, ptr, priv); | |
483 | } | |
484 | if (type_visitor->gather_array_type_func) | |
485 | type_visitor->gather_array_type_func(SIDE_TYPE_VISITOR_AFTER, side_array, priv); | |
486 | return tracer_gather_size(access_mode, ptr - orig_ptr); | |
487 | } | |
488 | ||
489 | static | |
490 | uint32_t type_visitor_gather_vla(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, const void *_length_ptr, void *priv) | |
491 | { | |
f0619c77 | 492 | enum side_type_gather_access_mode access_mode = side_enum_get(type_gather->u.side_vla.access_mode); |
980c17b1 | 493 | const struct side_type_vla *side_vla = &type_gather->u.side_vla.type; |
f0619c77 | 494 | const struct side_type *length_type = side_ptr_get(type_gather->u.side_vla.type.length_type); |
980c17b1 MD |
495 | const char *ptr = (const char *) _ptr, *orig_ptr; |
496 | const char *length_ptr = (const char *) _length_ptr; | |
497 | union int_value v = {}; | |
498 | uint32_t i, length; | |
499 | ||
500 | /* Access length */ | |
501 | switch (side_enum_get(length_type->type)) { | |
502 | case SIDE_TYPE_GATHER_INTEGER: | |
503 | break; | |
504 | default: | |
505 | fprintf(stderr, "<gather VLA expects integer gather length type>\n"); | |
506 | abort(); | |
507 | } | |
508 | v = tracer_load_gather_integer_value(&length_type->u.side_gather.u.side_integer, | |
509 | length_ptr); | |
510 | if (v.u[SIDE_INTEGER128_SPLIT_HIGH] || v.u[SIDE_INTEGER128_SPLIT_LOW] > UINT32_MAX) { | |
511 | fprintf(stderr, "Unexpected vla length value\n"); | |
512 | abort(); | |
513 | } | |
514 | length = (uint32_t) v.u[SIDE_INTEGER128_SPLIT_LOW]; | |
515 | if (type_visitor->gather_vla_type_func) | |
516 | type_visitor->gather_vla_type_func(SIDE_TYPE_VISITOR_BEFORE, side_vla, length, priv); | |
517 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_vla.offset); | |
518 | orig_ptr = ptr; | |
519 | for (i = 0; i < length; i++) { | |
520 | const struct side_type *elem_type = side_ptr_get(side_vla->elem_type); | |
521 | ||
522 | switch (side_enum_get(elem_type->type)) { | |
523 | case SIDE_TYPE_GATHER_VLA: | |
524 | fprintf(stderr, "<gather VLA only supported within gather structures>\n"); | |
525 | abort(); | |
526 | default: | |
527 | break; | |
528 | } | |
529 | ptr += visit_gather_elem(type_visitor, elem_type, ptr, priv); | |
530 | } | |
531 | if (type_visitor->gather_vla_type_func) | |
532 | type_visitor->gather_vla_type_func(SIDE_TYPE_VISITOR_AFTER, side_vla, length, priv); | |
533 | return tracer_gather_size(access_mode, ptr - orig_ptr); | |
534 | } | |
535 | ||
536 | static | |
537 | uint32_t type_visitor_gather_bool(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, void *priv) | |
538 | { | |
f0619c77 | 539 | enum side_type_gather_access_mode access_mode = side_enum_get(type_gather->u.side_bool.access_mode); |
980c17b1 MD |
540 | uint32_t bool_size_bytes = type_gather->u.side_bool.type.bool_size; |
541 | const char *ptr = (const char *) _ptr; | |
542 | union side_bool_value value; | |
543 | ||
544 | switch (bool_size_bytes) { | |
545 | case 1: | |
546 | case 2: | |
547 | case 4: | |
548 | case 8: | |
549 | break; | |
550 | default: | |
551 | abort(); | |
552 | } | |
553 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_bool.offset); | |
554 | memcpy(&value, ptr, bool_size_bytes); | |
555 | if (type_visitor->gather_bool_type_func) | |
556 | type_visitor->gather_bool_type_func(&type_gather->u.side_bool, &value, priv); | |
557 | return tracer_gather_size(access_mode, bool_size_bytes); | |
558 | } | |
559 | ||
560 | static | |
561 | uint32_t type_visitor_gather_byte(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, void *priv) | |
562 | { | |
f0619c77 | 563 | enum side_type_gather_access_mode access_mode = side_enum_get(type_gather->u.side_byte.access_mode); |
980c17b1 MD |
564 | const char *ptr = (const char *) _ptr; |
565 | uint8_t value; | |
566 | ||
567 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_byte.offset); | |
568 | memcpy(&value, ptr, 1); | |
569 | if (type_visitor->gather_byte_type_func) | |
570 | type_visitor->gather_byte_type_func(&type_gather->u.side_byte, &value, priv); | |
571 | return tracer_gather_size(access_mode, 1); | |
572 | } | |
573 | ||
574 | static | |
575 | uint32_t type_visitor_gather_integer(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, | |
576 | enum side_type_label integer_type, void *priv) | |
577 | { | |
f0619c77 | 578 | enum side_type_gather_access_mode access_mode = side_enum_get(type_gather->u.side_integer.access_mode); |
980c17b1 MD |
579 | uint32_t integer_size_bytes = type_gather->u.side_integer.type.integer_size; |
580 | const char *ptr = (const char *) _ptr; | |
581 | union side_integer_value value; | |
582 | ||
583 | switch (integer_size_bytes) { | |
584 | case 1: | |
585 | case 2: | |
586 | case 4: | |
587 | case 8: | |
588 | case 16: | |
589 | break; | |
590 | default: | |
591 | abort(); | |
592 | } | |
593 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_integer.offset); | |
594 | memcpy(&value, ptr, integer_size_bytes); | |
595 | switch (integer_type) { | |
596 | case SIDE_TYPE_GATHER_INTEGER: | |
597 | if (type_visitor->gather_integer_type_func) | |
598 | type_visitor->gather_integer_type_func(&type_gather->u.side_integer, &value, priv); | |
599 | break; | |
600 | case SIDE_TYPE_GATHER_POINTER: | |
601 | if (type_visitor->gather_pointer_type_func) | |
602 | type_visitor->gather_pointer_type_func(&type_gather->u.side_integer, &value, priv); | |
603 | break; | |
604 | default: | |
605 | fprintf(stderr, "Unexpected integer type\n"); | |
606 | abort(); | |
607 | } | |
608 | return tracer_gather_size(access_mode, integer_size_bytes); | |
609 | } | |
610 | ||
611 | static | |
612 | uint32_t type_visitor_gather_float(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, void *priv) | |
613 | { | |
f0619c77 | 614 | enum side_type_gather_access_mode access_mode = side_enum_get(type_gather->u.side_float.access_mode); |
980c17b1 MD |
615 | uint32_t float_size_bytes = type_gather->u.side_float.type.float_size; |
616 | const char *ptr = (const char *) _ptr; | |
617 | union side_float_value value; | |
618 | ||
619 | switch (float_size_bytes) { | |
620 | case 2: | |
621 | case 4: | |
622 | case 8: | |
623 | case 16: | |
624 | break; | |
625 | default: | |
626 | abort(); | |
627 | } | |
628 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_float.offset); | |
629 | memcpy(&value, ptr, float_size_bytes); | |
630 | if (type_visitor->gather_float_type_func) | |
631 | type_visitor->gather_float_type_func(&type_gather->u.side_float, &value, priv); | |
632 | return tracer_gather_size(access_mode, float_size_bytes); | |
633 | } | |
634 | ||
635 | static | |
636 | uint32_t type_visitor_gather_string(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, void *priv) | |
637 | { | |
638 | ||
f0619c77 | 639 | enum side_type_gather_access_mode access_mode = side_enum_get(type_gather->u.side_string.access_mode); |
980c17b1 MD |
640 | enum side_type_label_byte_order byte_order = side_enum_get(type_gather->u.side_string.type.byte_order); |
641 | uint8_t unit_size = type_gather->u.side_string.type.unit_size; | |
642 | const char *ptr = (const char *) _ptr; | |
643 | size_t string_len = 0; | |
644 | ||
645 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_string.offset); | |
646 | if (ptr) | |
647 | string_len = type_visitor_strlen(ptr, unit_size); | |
648 | if (type_visitor->gather_string_type_func) | |
649 | type_visitor->gather_string_type_func(&type_gather->u.side_string, ptr, unit_size, | |
650 | byte_order, string_len, priv); | |
651 | return tracer_gather_size(access_mode, string_len); | |
652 | } | |
653 | ||
654 | static | |
655 | uint32_t visit_gather_type(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const void *ptr, void *priv) | |
656 | { | |
657 | uint32_t len; | |
658 | ||
659 | switch (side_enum_get(type_desc->type)) { | |
660 | /* Gather basic types */ | |
661 | case SIDE_TYPE_GATHER_BOOL: | |
662 | len = type_visitor_gather_bool(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
663 | break; | |
664 | case SIDE_TYPE_GATHER_INTEGER: | |
665 | len = type_visitor_gather_integer(type_visitor, &type_desc->u.side_gather, ptr, SIDE_TYPE_GATHER_INTEGER, priv); | |
666 | break; | |
667 | case SIDE_TYPE_GATHER_BYTE: | |
668 | len = type_visitor_gather_byte(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
669 | break; | |
670 | case SIDE_TYPE_GATHER_POINTER: | |
671 | len = type_visitor_gather_integer(type_visitor, &type_desc->u.side_gather, ptr, SIDE_TYPE_GATHER_POINTER, priv); | |
672 | break; | |
673 | case SIDE_TYPE_GATHER_FLOAT: | |
674 | len = type_visitor_gather_float(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
675 | break; | |
676 | case SIDE_TYPE_GATHER_STRING: | |
677 | len = type_visitor_gather_string(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
678 | break; | |
679 | ||
680 | /* Gather enumeration types */ | |
681 | case SIDE_TYPE_GATHER_ENUM: | |
682 | len = type_visitor_gather_enum(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
683 | break; | |
684 | ||
685 | /* Gather compound types */ | |
686 | case SIDE_TYPE_GATHER_STRUCT: | |
687 | len = type_visitor_gather_struct(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
688 | break; | |
689 | case SIDE_TYPE_GATHER_ARRAY: | |
690 | len = type_visitor_gather_array(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
691 | break; | |
692 | case SIDE_TYPE_GATHER_VLA: | |
693 | len = type_visitor_gather_vla(type_visitor, &type_desc->u.side_gather, ptr, ptr, priv); | |
694 | break; | |
695 | default: | |
696 | fprintf(stderr, "<UNKNOWN GATHER TYPE>"); | |
697 | abort(); | |
698 | } | |
699 | return len; | |
700 | } | |
701 | ||
702 | static | |
703 | uint32_t visit_gather_elem(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const void *ptr, void *priv) | |
704 | { | |
705 | uint32_t len; | |
706 | ||
707 | if (type_visitor->elem_func) | |
708 | type_visitor->elem_func(SIDE_TYPE_VISITOR_BEFORE, type_desc, priv); | |
709 | len = visit_gather_type(type_visitor, type_desc, ptr, priv); | |
710 | if (type_visitor->elem_func) | |
711 | type_visitor->elem_func(SIDE_TYPE_VISITOR_AFTER, type_desc, priv); | |
712 | return len; | |
713 | } | |
714 | ||
715 | static | |
716 | uint32_t type_visitor_gather_enum(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, void *priv) | |
717 | { | |
718 | const struct side_type *enum_elem_type = side_ptr_get(type_gather->u.side_enum.elem_type); | |
719 | const struct side_type_gather_integer *side_integer = &enum_elem_type->u.side_gather.u.side_integer; | |
f0619c77 | 720 | enum side_type_gather_access_mode access_mode = side_enum_get(side_integer->access_mode); |
980c17b1 MD |
721 | uint32_t integer_size_bytes = side_integer->type.integer_size; |
722 | const char *ptr = (const char *) _ptr; | |
723 | union side_integer_value value; | |
724 | ||
725 | switch (integer_size_bytes) { | |
726 | case 1: | |
727 | case 2: | |
728 | case 4: | |
729 | case 8: | |
730 | case 16: | |
731 | break; | |
732 | default: | |
733 | abort(); | |
734 | } | |
735 | ptr = tracer_gather_access(access_mode, ptr + side_integer->offset); | |
736 | memcpy(&value, ptr, integer_size_bytes); | |
737 | if (type_visitor->gather_enum_type_func) | |
738 | type_visitor->gather_enum_type_func(&type_gather->u.side_enum, &value, priv); | |
739 | return tracer_gather_size(access_mode, integer_size_bytes); | |
740 | } | |
741 | ||
742 | static | |
743 | void visit_dynamic_field(const struct side_type_visitor *type_visitor, const struct side_arg_dynamic_field *field, void *priv) | |
744 | { | |
745 | if (type_visitor->dynamic_field_func) | |
746 | type_visitor->dynamic_field_func(SIDE_TYPE_VISITOR_BEFORE, field, priv); | |
747 | visit_dynamic_type(type_visitor, &field->elem, priv); | |
748 | if (type_visitor->dynamic_field_func) | |
749 | type_visitor->dynamic_field_func(SIDE_TYPE_VISITOR_AFTER, field, priv); | |
750 | } | |
751 | ||
752 | static | |
753 | void type_visitor_dynamic_struct(const struct side_type_visitor *type_visitor, const struct side_arg_dynamic_struct *dynamic_struct, void *priv) | |
754 | { | |
755 | const struct side_arg_dynamic_field *fields = side_ptr_get(dynamic_struct->fields); | |
756 | uint32_t i, len = dynamic_struct->len; | |
757 | ||
758 | if (type_visitor->dynamic_struct_func) | |
759 | type_visitor->dynamic_struct_func(SIDE_TYPE_VISITOR_BEFORE, dynamic_struct, priv); | |
760 | for (i = 0; i < len; i++) | |
761 | visit_dynamic_field(type_visitor, &fields[i], priv); | |
762 | if (type_visitor->dynamic_struct_func) | |
763 | type_visitor->dynamic_struct_func(SIDE_TYPE_VISITOR_AFTER, dynamic_struct, priv); | |
764 | } | |
765 | ||
766 | struct tracer_dynamic_struct_visitor_priv { | |
767 | const struct side_type_visitor *type_visitor; | |
768 | void *priv; | |
769 | int i; | |
770 | }; | |
771 | ||
772 | static | |
773 | enum side_visitor_status tracer_dynamic_struct_write_elem_cb( | |
774 | const struct side_tracer_dynamic_struct_visitor_ctx *tracer_ctx, | |
775 | const struct side_arg_dynamic_field *dynamic_field) | |
776 | { | |
777 | struct tracer_dynamic_struct_visitor_priv *tracer_priv = | |
778 | (struct tracer_dynamic_struct_visitor_priv *) tracer_ctx->priv; | |
779 | ||
780 | visit_dynamic_field(tracer_priv->type_visitor, dynamic_field, tracer_priv->priv); | |
781 | return SIDE_VISITOR_STATUS_OK; | |
782 | } | |
783 | ||
784 | static | |
785 | void type_visitor_dynamic_struct_visitor(const struct side_type_visitor *type_visitor, const struct side_arg *item, void *priv) | |
786 | { | |
787 | struct side_arg_dynamic_struct_visitor *dynamic_struct_visitor; | |
788 | struct tracer_dynamic_struct_visitor_priv tracer_priv = { | |
789 | .type_visitor = type_visitor, | |
790 | .priv = priv, | |
791 | .i = 0, | |
792 | }; | |
793 | const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx = { | |
794 | .write_field = tracer_dynamic_struct_write_elem_cb, | |
795 | .priv = &tracer_priv, | |
796 | }; | |
797 | enum side_visitor_status status; | |
798 | void *app_ctx; | |
799 | ||
800 | if (type_visitor->dynamic_struct_visitor_func) | |
801 | type_visitor->dynamic_struct_visitor_func(SIDE_TYPE_VISITOR_BEFORE, item, priv); | |
802 | dynamic_struct_visitor = side_ptr_get(item->u.side_dynamic.side_dynamic_struct_visitor); | |
803 | if (!dynamic_struct_visitor) | |
804 | abort(); | |
805 | app_ctx = side_ptr_get(dynamic_struct_visitor->app_ctx); | |
806 | status = side_ptr_get(dynamic_struct_visitor->visitor)(&tracer_ctx, app_ctx); | |
807 | switch (status) { | |
808 | case SIDE_VISITOR_STATUS_OK: | |
809 | break; | |
810 | case SIDE_VISITOR_STATUS_ERROR: | |
811 | fprintf(stderr, "ERROR: Visitor error\n"); | |
812 | abort(); | |
813 | } | |
814 | if (type_visitor->dynamic_struct_visitor_func) | |
815 | type_visitor->dynamic_struct_visitor_func(SIDE_TYPE_VISITOR_AFTER, item, priv); | |
816 | } | |
817 | ||
818 | static | |
819 | void type_visitor_dynamic_vla(const struct side_type_visitor *type_visitor, const struct side_arg_dynamic_vla *vla, void *priv) | |
820 | { | |
821 | const struct side_arg *sav = side_ptr_get(vla->sav); | |
822 | uint32_t i, side_sav_len = vla->len; | |
823 | ||
824 | if (type_visitor->dynamic_vla_func) | |
825 | type_visitor->dynamic_vla_func(SIDE_TYPE_VISITOR_BEFORE, vla, priv); | |
826 | for (i = 0; i < side_sav_len; i++) | |
827 | visit_dynamic_elem(type_visitor, &sav[i], priv); | |
828 | if (type_visitor->dynamic_vla_func) | |
829 | type_visitor->dynamic_vla_func(SIDE_TYPE_VISITOR_AFTER, vla, priv); | |
830 | } | |
831 | ||
832 | struct tracer_dynamic_vla_visitor_priv { | |
833 | const struct side_type_visitor *type_visitor; | |
834 | void *priv; | |
835 | int i; | |
836 | }; | |
837 | ||
838 | static | |
839 | enum side_visitor_status tracer_dynamic_vla_write_elem_cb( | |
840 | const struct side_tracer_visitor_ctx *tracer_ctx, | |
841 | const struct side_arg *elem) | |
842 | { | |
843 | struct tracer_dynamic_vla_visitor_priv *tracer_priv = | |
844 | (struct tracer_dynamic_vla_visitor_priv *) tracer_ctx->priv; | |
845 | ||
846 | visit_dynamic_elem(tracer_priv->type_visitor, elem, tracer_priv->priv); | |
847 | return SIDE_VISITOR_STATUS_OK; | |
848 | } | |
849 | ||
850 | static | |
851 | void type_visitor_dynamic_vla_visitor(const struct side_type_visitor *type_visitor, const struct side_arg *item, void *priv) | |
852 | { | |
853 | struct side_arg_dynamic_vla_visitor *dynamic_vla_visitor; | |
854 | struct tracer_dynamic_vla_visitor_priv tracer_priv = { | |
855 | .type_visitor = type_visitor, | |
856 | .priv = priv, | |
857 | .i = 0, | |
858 | }; | |
859 | const struct side_tracer_visitor_ctx tracer_ctx = { | |
860 | .write_elem = tracer_dynamic_vla_write_elem_cb, | |
861 | .priv = &tracer_priv, | |
862 | }; | |
863 | enum side_visitor_status status; | |
864 | void *app_ctx; | |
865 | ||
866 | if (type_visitor->dynamic_vla_visitor_func) | |
867 | type_visitor->dynamic_vla_visitor_func(SIDE_TYPE_VISITOR_BEFORE, item, priv); | |
868 | dynamic_vla_visitor = side_ptr_get(item->u.side_dynamic.side_dynamic_vla_visitor); | |
869 | if (!dynamic_vla_visitor) | |
870 | abort(); | |
871 | app_ctx = side_ptr_get(dynamic_vla_visitor->app_ctx); | |
872 | status = side_ptr_get(dynamic_vla_visitor->visitor)(&tracer_ctx, app_ctx); | |
873 | switch (status) { | |
874 | case SIDE_VISITOR_STATUS_OK: | |
875 | break; | |
876 | case SIDE_VISITOR_STATUS_ERROR: | |
877 | fprintf(stderr, "ERROR: Visitor error\n"); | |
878 | abort(); | |
879 | } | |
880 | if (type_visitor->dynamic_vla_visitor_func) | |
881 | type_visitor->dynamic_vla_visitor_func(SIDE_TYPE_VISITOR_AFTER, item, priv); | |
882 | } | |
883 | ||
884 | static | |
885 | void visit_dynamic_type(const struct side_type_visitor *type_visitor, const struct side_arg *dynamic_item, void *priv) | |
886 | { | |
887 | switch (side_enum_get(dynamic_item->type)) { | |
888 | /* Dynamic basic types */ | |
889 | case SIDE_TYPE_DYNAMIC_NULL: | |
890 | if (type_visitor->dynamic_null_func) | |
891 | type_visitor->dynamic_null_func(dynamic_item, priv); | |
892 | break; | |
893 | case SIDE_TYPE_DYNAMIC_BOOL: | |
894 | if (type_visitor->dynamic_bool_func) | |
895 | type_visitor->dynamic_bool_func(dynamic_item, priv); | |
896 | break; | |
897 | case SIDE_TYPE_DYNAMIC_INTEGER: | |
898 | if (type_visitor->dynamic_integer_func) | |
899 | type_visitor->dynamic_integer_func(dynamic_item, priv); | |
900 | break; | |
901 | case SIDE_TYPE_DYNAMIC_BYTE: | |
902 | if (type_visitor->dynamic_byte_func) | |
903 | type_visitor->dynamic_byte_func(dynamic_item, priv); | |
904 | break; | |
905 | case SIDE_TYPE_DYNAMIC_POINTER: | |
906 | if (type_visitor->dynamic_pointer_func) | |
907 | type_visitor->dynamic_pointer_func(dynamic_item, priv); | |
908 | break; | |
909 | case SIDE_TYPE_DYNAMIC_FLOAT: | |
910 | if (type_visitor->dynamic_float_func) | |
911 | type_visitor->dynamic_float_func(dynamic_item, priv); | |
912 | break; | |
913 | case SIDE_TYPE_DYNAMIC_STRING: | |
914 | if (type_visitor->dynamic_string_func) | |
915 | type_visitor->dynamic_string_func(dynamic_item, priv); | |
916 | break; | |
917 | ||
918 | /* Dynamic compound types */ | |
919 | case SIDE_TYPE_DYNAMIC_STRUCT: | |
920 | type_visitor_dynamic_struct(type_visitor, side_ptr_get(dynamic_item->u.side_dynamic.side_dynamic_struct), priv); | |
921 | break; | |
922 | case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR: | |
923 | type_visitor_dynamic_struct_visitor(type_visitor, dynamic_item, priv); | |
924 | break; | |
925 | case SIDE_TYPE_DYNAMIC_VLA: | |
926 | type_visitor_dynamic_vla(type_visitor, side_ptr_get(dynamic_item->u.side_dynamic.side_dynamic_vla), priv); | |
927 | break; | |
928 | case SIDE_TYPE_DYNAMIC_VLA_VISITOR: | |
929 | type_visitor_dynamic_vla_visitor(type_visitor, dynamic_item, priv); | |
930 | break; | |
931 | default: | |
932 | fprintf(stderr, "<UNKNOWN TYPE>\n"); | |
933 | abort(); | |
934 | } | |
935 | } | |
936 | ||
937 | static | |
938 | void visit_dynamic_elem(const struct side_type_visitor *type_visitor, const struct side_arg *dynamic_item, void *priv) | |
939 | { | |
940 | if (type_visitor->elem_func) | |
941 | type_visitor->dynamic_elem_func(SIDE_TYPE_VISITOR_BEFORE, dynamic_item, priv); | |
942 | visit_dynamic_type(type_visitor, dynamic_item, priv); | |
943 | if (type_visitor->elem_func) | |
944 | type_visitor->dynamic_elem_func(SIDE_TYPE_VISITOR_AFTER, dynamic_item, priv); | |
945 | } | |
946 | ||
947 | void side_visit_type(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const struct side_arg *item, void *priv) | |
948 | { | |
949 | enum side_type_label type; | |
950 | ||
951 | switch (side_enum_get(type_desc->type)) { | |
952 | case SIDE_TYPE_ENUM: | |
953 | switch (side_enum_get(item->type)) { | |
954 | case SIDE_TYPE_U8: | |
955 | case SIDE_TYPE_U16: | |
956 | case SIDE_TYPE_U32: | |
957 | case SIDE_TYPE_U64: | |
958 | case SIDE_TYPE_U128: | |
959 | case SIDE_TYPE_S8: | |
960 | case SIDE_TYPE_S16: | |
961 | case SIDE_TYPE_S32: | |
962 | case SIDE_TYPE_S64: | |
963 | case SIDE_TYPE_S128: | |
964 | break; | |
965 | default: | |
966 | fprintf(stderr, "ERROR: type mismatch between description and arguments\n"); | |
967 | abort(); | |
968 | break; | |
969 | } | |
970 | break; | |
971 | ||
972 | case SIDE_TYPE_ENUM_BITMAP: | |
973 | switch (side_enum_get(item->type)) { | |
974 | case SIDE_TYPE_U8: | |
975 | case SIDE_TYPE_BYTE: | |
976 | case SIDE_TYPE_U16: | |
977 | case SIDE_TYPE_U32: | |
978 | case SIDE_TYPE_U64: | |
979 | case SIDE_TYPE_U128: | |
980 | case SIDE_TYPE_ARRAY: | |
981 | case SIDE_TYPE_VLA: | |
982 | break; | |
983 | default: | |
984 | fprintf(stderr, "ERROR: type mismatch between description and arguments\n"); | |
985 | abort(); | |
986 | break; | |
987 | } | |
988 | break; | |
989 | ||
990 | case SIDE_TYPE_GATHER_ENUM: | |
991 | switch (side_enum_get(item->type)) { | |
992 | case SIDE_TYPE_GATHER_INTEGER: | |
993 | break; | |
994 | default: | |
995 | fprintf(stderr, "ERROR: type mismatch between description and arguments\n"); | |
996 | abort(); | |
997 | break; | |
998 | } | |
999 | break; | |
1000 | ||
1001 | case SIDE_TYPE_DYNAMIC: | |
1002 | switch (side_enum_get(item->type)) { | |
1003 | case SIDE_TYPE_DYNAMIC_NULL: | |
1004 | case SIDE_TYPE_DYNAMIC_BOOL: | |
1005 | case SIDE_TYPE_DYNAMIC_INTEGER: | |
1006 | case SIDE_TYPE_DYNAMIC_BYTE: | |
1007 | case SIDE_TYPE_DYNAMIC_POINTER: | |
1008 | case SIDE_TYPE_DYNAMIC_FLOAT: | |
1009 | case SIDE_TYPE_DYNAMIC_STRING: | |
1010 | case SIDE_TYPE_DYNAMIC_STRUCT: | |
1011 | case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR: | |
1012 | case SIDE_TYPE_DYNAMIC_VLA: | |
1013 | case SIDE_TYPE_DYNAMIC_VLA_VISITOR: | |
1014 | break; | |
1015 | default: | |
1016 | fprintf(stderr, "ERROR: Unexpected dynamic type\n"); | |
1017 | abort(); | |
1018 | break; | |
1019 | } | |
1020 | break; | |
1021 | ||
1022 | default: | |
1023 | if (side_enum_get(type_desc->type) != side_enum_get(item->type)) { | |
1024 | fprintf(stderr, "ERROR: type mismatch between description and arguments\n"); | |
1025 | abort(); | |
1026 | } | |
1027 | break; | |
1028 | } | |
1029 | ||
1030 | if (side_enum_get(type_desc->type) == SIDE_TYPE_ENUM || side_enum_get(type_desc->type) == SIDE_TYPE_ENUM_BITMAP || side_enum_get(type_desc->type) == SIDE_TYPE_GATHER_ENUM) | |
1031 | type = side_enum_get(type_desc->type); | |
1032 | else | |
1033 | type = side_enum_get(item->type); | |
1034 | ||
1035 | switch (type) { | |
1036 | /* Stack-copy basic types */ | |
1037 | case SIDE_TYPE_NULL: | |
1038 | if (type_visitor->null_type_func) | |
1039 | type_visitor->null_type_func(type_desc, item, priv); | |
1040 | break; | |
1041 | case SIDE_TYPE_BOOL: | |
1042 | if (type_visitor->bool_type_func) | |
1043 | type_visitor->bool_type_func(type_desc, item, priv); | |
1044 | break; | |
1045 | case SIDE_TYPE_U8: /* Fallthrough */ | |
1046 | case SIDE_TYPE_U16: /* Fallthrough */ | |
1047 | case SIDE_TYPE_U32: /* Fallthrough */ | |
1048 | case SIDE_TYPE_U64: /* Fallthrough */ | |
1049 | case SIDE_TYPE_U128: /* Fallthrough */ | |
1050 | case SIDE_TYPE_S8: /* Fallthrough */ | |
1051 | case SIDE_TYPE_S16: /* Fallthrough */ | |
1052 | case SIDE_TYPE_S32: /* Fallthrough */ | |
1053 | case SIDE_TYPE_S64: /* Fallthrough */ | |
1054 | case SIDE_TYPE_S128: | |
1055 | if (type_visitor->integer_type_func) | |
1056 | type_visitor->integer_type_func(type_desc, item, priv); | |
1057 | break; | |
1058 | case SIDE_TYPE_BYTE: | |
1059 | if (type_visitor->byte_type_func) | |
1060 | type_visitor->byte_type_func(type_desc, item, priv); | |
1061 | break; | |
1062 | case SIDE_TYPE_POINTER: | |
1063 | if (type_visitor->pointer_type_func) | |
1064 | type_visitor->pointer_type_func(type_desc, item, priv); | |
1065 | break; | |
1066 | case SIDE_TYPE_FLOAT_BINARY16: /* Fallthrough */ | |
1067 | case SIDE_TYPE_FLOAT_BINARY32: /* Fallthrough */ | |
1068 | case SIDE_TYPE_FLOAT_BINARY64: /* Fallthrough */ | |
1069 | case SIDE_TYPE_FLOAT_BINARY128: | |
1070 | if (type_visitor->float_type_func) | |
1071 | type_visitor->float_type_func(type_desc, item, priv); | |
1072 | break; | |
1073 | case SIDE_TYPE_STRING_UTF8: /* Fallthrough */ | |
1074 | case SIDE_TYPE_STRING_UTF16: /* Fallthrough */ | |
1075 | case SIDE_TYPE_STRING_UTF32: | |
1076 | if (type_visitor->string_type_func) | |
1077 | type_visitor->string_type_func(type_desc, item, priv); | |
1078 | break; | |
1079 | case SIDE_TYPE_ENUM: | |
1080 | if (type_visitor->enum_type_func) | |
1081 | type_visitor->enum_type_func(type_desc, item, priv); | |
1082 | break; | |
1083 | case SIDE_TYPE_ENUM_BITMAP: | |
1084 | if (type_visitor->enum_bitmap_type_func) | |
1085 | type_visitor->enum_bitmap_type_func(type_desc, item, priv); | |
1086 | break; | |
1087 | ||
1088 | /* Stack-copy compound types */ | |
1089 | case SIDE_TYPE_STRUCT: | |
1090 | type_visitor_struct(type_visitor, type_desc, side_ptr_get(item->u.side_static.side_struct), priv); | |
1091 | break; | |
1092 | case SIDE_TYPE_VARIANT: | |
1093 | type_visitor_variant(type_visitor, type_desc, side_ptr_get(item->u.side_static.side_variant), priv); | |
1094 | break; | |
1095 | case SIDE_TYPE_ARRAY: | |
1096 | type_visitor_array(type_visitor, type_desc, side_ptr_get(item->u.side_static.side_array), priv); | |
1097 | break; | |
1098 | case SIDE_TYPE_VLA: | |
1099 | type_visitor_vla(type_visitor, type_desc, side_ptr_get(item->u.side_static.side_vla), priv); | |
1100 | break; | |
1101 | case SIDE_TYPE_VLA_VISITOR: | |
1102 | type_visitor_vla_visitor(type_visitor, type_desc, side_ptr_get(item->u.side_static.side_vla_visitor), priv); | |
1103 | break; | |
1104 | ||
1105 | /* Gather basic types */ | |
1106 | case SIDE_TYPE_GATHER_BOOL: | |
1107 | (void) type_visitor_gather_bool(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_bool_gather_ptr), priv); | |
1108 | break; | |
1109 | case SIDE_TYPE_GATHER_INTEGER: | |
1110 | (void) type_visitor_gather_integer(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_integer_gather_ptr), SIDE_TYPE_GATHER_INTEGER, priv); | |
1111 | break; | |
1112 | case SIDE_TYPE_GATHER_BYTE: | |
1113 | (void) type_visitor_gather_byte(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_byte_gather_ptr), priv); | |
1114 | break; | |
1115 | case SIDE_TYPE_GATHER_POINTER: | |
1116 | (void) type_visitor_gather_integer(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_integer_gather_ptr), SIDE_TYPE_GATHER_POINTER, priv); | |
1117 | break; | |
1118 | case SIDE_TYPE_GATHER_FLOAT: | |
1119 | (void) type_visitor_gather_float(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_float_gather_ptr), priv); | |
1120 | break; | |
1121 | case SIDE_TYPE_GATHER_STRING: | |
1122 | (void) type_visitor_gather_string(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_string_gather_ptr), priv); | |
1123 | break; | |
1124 | ||
1125 | /* Gather compound type */ | |
1126 | case SIDE_TYPE_GATHER_STRUCT: | |
1127 | (void) type_visitor_gather_struct(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_struct_gather_ptr), priv); | |
1128 | break; | |
1129 | case SIDE_TYPE_GATHER_ARRAY: | |
1130 | (void) type_visitor_gather_array(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_array_gather_ptr), priv); | |
1131 | break; | |
1132 | case SIDE_TYPE_GATHER_VLA: | |
1133 | (void) type_visitor_gather_vla(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_array_gather_ptr), | |
1134 | side_ptr_get(item->u.side_static.side_vla_gather.length_ptr), priv); | |
1135 | break; | |
1136 | ||
1137 | /* Gather enumeration types */ | |
1138 | case SIDE_TYPE_GATHER_ENUM: | |
1139 | (void) type_visitor_gather_enum(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_integer_gather_ptr), priv); | |
1140 | break; | |
1141 | ||
1142 | /* Dynamic basic types */ | |
1143 | case SIDE_TYPE_DYNAMIC_NULL: /* Fallthrough */ | |
1144 | case SIDE_TYPE_DYNAMIC_BOOL: /* Fallthrough */ | |
1145 | case SIDE_TYPE_DYNAMIC_INTEGER: /* Fallthrough */ | |
1146 | case SIDE_TYPE_DYNAMIC_BYTE: /* Fallthrough */ | |
1147 | case SIDE_TYPE_DYNAMIC_POINTER: /* Fallthrough */ | |
1148 | case SIDE_TYPE_DYNAMIC_FLOAT: /* Fallthrough */ | |
1149 | case SIDE_TYPE_DYNAMIC_STRING: /* Fallthrough */ | |
1150 | ||
1151 | /* Dynamic compound types */ | |
1152 | case SIDE_TYPE_DYNAMIC_STRUCT: /* Fallthrough */ | |
1153 | case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR: /* Fallthrough */ | |
1154 | case SIDE_TYPE_DYNAMIC_VLA: /* Fallthrough */ | |
1155 | case SIDE_TYPE_DYNAMIC_VLA_VISITOR: | |
1156 | visit_dynamic_type(type_visitor, item, priv); | |
1157 | break; | |
1158 | ||
1159 | default: | |
1160 | fprintf(stderr, "<UNKNOWN TYPE>\n"); | |
1161 | abort(); | |
1162 | } | |
1163 | } | |
1164 | ||
1165 | void type_visitor_event(const struct side_type_visitor *type_visitor, | |
1166 | const struct side_event_description *desc, | |
1167 | const struct side_arg_vec *side_arg_vec, | |
1168 | const struct side_arg_dynamic_struct *var_struct, | |
1169 | void *caller_addr, void *priv) | |
1170 | { | |
1171 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); | |
1172 | uint32_t i, side_sav_len = side_arg_vec->len; | |
1173 | ||
1174 | if (desc->nr_fields != side_sav_len) { | |
1175 | fprintf(stderr, "ERROR: number of fields mismatch between description and arguments\n"); | |
1176 | abort(); | |
1177 | } | |
1178 | if (type_visitor->event_func) | |
1179 | type_visitor->event_func(SIDE_TYPE_VISITOR_BEFORE, desc, side_arg_vec, var_struct, caller_addr, priv); | |
1180 | if (side_sav_len) { | |
1181 | if (type_visitor->static_fields_func) | |
1182 | type_visitor->static_fields_func(SIDE_TYPE_VISITOR_BEFORE, side_arg_vec, priv); | |
1183 | for (i = 0; i < side_sav_len; i++) | |
1184 | side_visit_field(type_visitor, &side_ptr_get(desc->fields)[i], &sav[i], priv); | |
1185 | if (type_visitor->static_fields_func) | |
1186 | type_visitor->static_fields_func(SIDE_TYPE_VISITOR_AFTER, side_arg_vec, priv); | |
1187 | } | |
1188 | if (var_struct) { | |
1189 | uint32_t var_struct_len = var_struct->len; | |
1190 | ||
1191 | if (type_visitor->variadic_fields_func) | |
1192 | type_visitor->variadic_fields_func(SIDE_TYPE_VISITOR_BEFORE, var_struct, priv); | |
1193 | for (i = 0; i < var_struct_len; i++) | |
1194 | visit_dynamic_field(type_visitor, &side_ptr_get(var_struct->fields)[i], priv); | |
1195 | if (type_visitor->variadic_fields_func) | |
1196 | type_visitor->variadic_fields_func(SIDE_TYPE_VISITOR_AFTER, var_struct, priv); | |
1197 | } | |
1198 | if (type_visitor->event_func) | |
1199 | type_visitor->event_func(SIDE_TYPE_VISITOR_AFTER, desc, side_arg_vec, var_struct, caller_addr, priv); | |
1200 | } |