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, | |
360 | .elem_type = side_ptr_get(type_desc->u.side_vla_visitor.elem_type), | |
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) | |
374 | type_visitor->vla_visitor_type_func(SIDE_TYPE_VISITOR_BEFORE, &type_desc->u.side_vla_visitor, vla_visitor, priv); | |
375 | app_ctx = side_ptr_get(vla_visitor->app_ctx); | |
376 | func = side_ptr_get(type_desc->u.side_vla_visitor.visitor); | |
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) | |
386 | type_visitor->vla_visitor_type_func(SIDE_TYPE_VISITOR_AFTER, &type_desc->u.side_vla_visitor, vla_visitor, priv); | |
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 | { | |
421 | enum side_type_gather_access_mode access_mode = | |
422 | (enum side_type_gather_access_mode) side_integer->access_mode; | |
423 | uint32_t integer_size_bytes = side_integer->type.integer_size; | |
424 | const char *ptr = (const char *) _ptr; | |
425 | union side_integer_value value; | |
426 | ||
427 | ptr = tracer_gather_access(access_mode, ptr + side_integer->offset); | |
428 | memcpy(&value, ptr, integer_size_bytes); | |
429 | return tracer_load_integer_value(&side_integer->type, &value, | |
430 | side_integer->offset_bits, NULL); | |
431 | } | |
432 | ||
433 | static | |
434 | void visit_gather_field(const struct side_type_visitor *type_visitor, const struct side_event_field *field, const void *ptr, void *priv) | |
435 | { | |
436 | if (type_visitor->field_func) | |
437 | type_visitor->field_func(SIDE_TYPE_VISITOR_BEFORE, field, priv); | |
438 | (void) visit_gather_type(type_visitor, &field->side_type, ptr, priv); | |
439 | if (type_visitor->field_func) | |
440 | type_visitor->field_func(SIDE_TYPE_VISITOR_AFTER, field, priv); | |
441 | } | |
442 | ||
443 | static | |
444 | 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) | |
445 | { | |
446 | enum side_type_gather_access_mode access_mode = | |
447 | (enum side_type_gather_access_mode) type_gather->u.side_struct.access_mode; | |
448 | const struct side_type_struct *side_struct = side_ptr_get(type_gather->u.side_struct.type); | |
449 | const char *ptr = (const char *) _ptr; | |
450 | uint32_t i; | |
451 | ||
452 | if (type_visitor->gather_struct_type_func) | |
453 | type_visitor->gather_struct_type_func(SIDE_TYPE_VISITOR_BEFORE, side_struct, priv); | |
454 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_struct.offset); | |
455 | for (i = 0; i < side_struct->nr_fields; i++) | |
456 | visit_gather_field(type_visitor, &side_ptr_get(side_struct->fields)[i], ptr, priv); | |
457 | if (type_visitor->gather_struct_type_func) | |
458 | type_visitor->gather_struct_type_func(SIDE_TYPE_VISITOR_AFTER, side_struct, priv); | |
459 | return tracer_gather_size(access_mode, type_gather->u.side_struct.size); | |
460 | } | |
461 | ||
462 | static | |
463 | 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) | |
464 | { | |
465 | enum side_type_gather_access_mode access_mode = | |
466 | (enum side_type_gather_access_mode) type_gather->u.side_array.access_mode; | |
467 | const struct side_type_array *side_array = &type_gather->u.side_array.type; | |
468 | const char *ptr = (const char *) _ptr, *orig_ptr; | |
469 | uint32_t i; | |
470 | ||
471 | if (type_visitor->gather_array_type_func) | |
472 | type_visitor->gather_array_type_func(SIDE_TYPE_VISITOR_BEFORE, side_array, priv); | |
473 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_array.offset); | |
474 | orig_ptr = ptr; | |
475 | for (i = 0; i < side_array->length; i++) { | |
476 | const struct side_type *elem_type = side_ptr_get(side_array->elem_type); | |
477 | ||
478 | switch (side_enum_get(elem_type->type)) { | |
479 | case SIDE_TYPE_GATHER_VLA: | |
480 | fprintf(stderr, "<gather VLA only supported within gather structures>\n"); | |
481 | abort(); | |
482 | default: | |
483 | break; | |
484 | } | |
485 | ptr += visit_gather_elem(type_visitor, elem_type, ptr, priv); | |
486 | } | |
487 | if (type_visitor->gather_array_type_func) | |
488 | type_visitor->gather_array_type_func(SIDE_TYPE_VISITOR_AFTER, side_array, priv); | |
489 | return tracer_gather_size(access_mode, ptr - orig_ptr); | |
490 | } | |
491 | ||
492 | static | |
493 | 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) | |
494 | { | |
495 | enum side_type_gather_access_mode access_mode = | |
496 | (enum side_type_gather_access_mode) type_gather->u.side_vla.access_mode; | |
497 | const struct side_type_vla *side_vla = &type_gather->u.side_vla.type; | |
498 | const struct side_type *length_type = side_ptr_get(type_gather->u.side_vla.length_type); | |
499 | const char *ptr = (const char *) _ptr, *orig_ptr; | |
500 | const char *length_ptr = (const char *) _length_ptr; | |
501 | union int_value v = {}; | |
502 | uint32_t i, length; | |
503 | ||
504 | /* Access length */ | |
505 | switch (side_enum_get(length_type->type)) { | |
506 | case SIDE_TYPE_GATHER_INTEGER: | |
507 | break; | |
508 | default: | |
509 | fprintf(stderr, "<gather VLA expects integer gather length type>\n"); | |
510 | abort(); | |
511 | } | |
512 | v = tracer_load_gather_integer_value(&length_type->u.side_gather.u.side_integer, | |
513 | length_ptr); | |
514 | if (v.u[SIDE_INTEGER128_SPLIT_HIGH] || v.u[SIDE_INTEGER128_SPLIT_LOW] > UINT32_MAX) { | |
515 | fprintf(stderr, "Unexpected vla length value\n"); | |
516 | abort(); | |
517 | } | |
518 | length = (uint32_t) v.u[SIDE_INTEGER128_SPLIT_LOW]; | |
519 | if (type_visitor->gather_vla_type_func) | |
520 | type_visitor->gather_vla_type_func(SIDE_TYPE_VISITOR_BEFORE, side_vla, length, priv); | |
521 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_vla.offset); | |
522 | orig_ptr = ptr; | |
523 | for (i = 0; i < length; i++) { | |
524 | const struct side_type *elem_type = side_ptr_get(side_vla->elem_type); | |
525 | ||
526 | switch (side_enum_get(elem_type->type)) { | |
527 | case SIDE_TYPE_GATHER_VLA: | |
528 | fprintf(stderr, "<gather VLA only supported within gather structures>\n"); | |
529 | abort(); | |
530 | default: | |
531 | break; | |
532 | } | |
533 | ptr += visit_gather_elem(type_visitor, elem_type, ptr, priv); | |
534 | } | |
535 | if (type_visitor->gather_vla_type_func) | |
536 | type_visitor->gather_vla_type_func(SIDE_TYPE_VISITOR_AFTER, side_vla, length, priv); | |
537 | return tracer_gather_size(access_mode, ptr - orig_ptr); | |
538 | } | |
539 | ||
540 | static | |
541 | 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) | |
542 | { | |
543 | enum side_type_gather_access_mode access_mode = | |
544 | (enum side_type_gather_access_mode) type_gather->u.side_bool.access_mode; | |
545 | uint32_t bool_size_bytes = type_gather->u.side_bool.type.bool_size; | |
546 | const char *ptr = (const char *) _ptr; | |
547 | union side_bool_value value; | |
548 | ||
549 | switch (bool_size_bytes) { | |
550 | case 1: | |
551 | case 2: | |
552 | case 4: | |
553 | case 8: | |
554 | break; | |
555 | default: | |
556 | abort(); | |
557 | } | |
558 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_bool.offset); | |
559 | memcpy(&value, ptr, bool_size_bytes); | |
560 | if (type_visitor->gather_bool_type_func) | |
561 | type_visitor->gather_bool_type_func(&type_gather->u.side_bool, &value, priv); | |
562 | return tracer_gather_size(access_mode, bool_size_bytes); | |
563 | } | |
564 | ||
565 | static | |
566 | 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) | |
567 | { | |
568 | enum side_type_gather_access_mode access_mode = | |
569 | (enum side_type_gather_access_mode) type_gather->u.side_byte.access_mode; | |
570 | const char *ptr = (const char *) _ptr; | |
571 | uint8_t value; | |
572 | ||
573 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_byte.offset); | |
574 | memcpy(&value, ptr, 1); | |
575 | if (type_visitor->gather_byte_type_func) | |
576 | type_visitor->gather_byte_type_func(&type_gather->u.side_byte, &value, priv); | |
577 | return tracer_gather_size(access_mode, 1); | |
578 | } | |
579 | ||
580 | static | |
581 | uint32_t type_visitor_gather_integer(const struct side_type_visitor *type_visitor, const struct side_type_gather *type_gather, const void *_ptr, | |
582 | enum side_type_label integer_type, void *priv) | |
583 | { | |
584 | enum side_type_gather_access_mode access_mode = | |
585 | (enum side_type_gather_access_mode) type_gather->u.side_integer.access_mode; | |
586 | uint32_t integer_size_bytes = type_gather->u.side_integer.type.integer_size; | |
587 | const char *ptr = (const char *) _ptr; | |
588 | union side_integer_value value; | |
589 | ||
590 | switch (integer_size_bytes) { | |
591 | case 1: | |
592 | case 2: | |
593 | case 4: | |
594 | case 8: | |
595 | case 16: | |
596 | break; | |
597 | default: | |
598 | abort(); | |
599 | } | |
600 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_integer.offset); | |
601 | memcpy(&value, ptr, integer_size_bytes); | |
602 | switch (integer_type) { | |
603 | case SIDE_TYPE_GATHER_INTEGER: | |
604 | if (type_visitor->gather_integer_type_func) | |
605 | type_visitor->gather_integer_type_func(&type_gather->u.side_integer, &value, priv); | |
606 | break; | |
607 | case SIDE_TYPE_GATHER_POINTER: | |
608 | if (type_visitor->gather_pointer_type_func) | |
609 | type_visitor->gather_pointer_type_func(&type_gather->u.side_integer, &value, priv); | |
610 | break; | |
611 | default: | |
612 | fprintf(stderr, "Unexpected integer type\n"); | |
613 | abort(); | |
614 | } | |
615 | return tracer_gather_size(access_mode, integer_size_bytes); | |
616 | } | |
617 | ||
618 | static | |
619 | 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) | |
620 | { | |
621 | enum side_type_gather_access_mode access_mode = | |
622 | (enum side_type_gather_access_mode) type_gather->u.side_float.access_mode; | |
623 | uint32_t float_size_bytes = type_gather->u.side_float.type.float_size; | |
624 | const char *ptr = (const char *) _ptr; | |
625 | union side_float_value value; | |
626 | ||
627 | switch (float_size_bytes) { | |
628 | case 2: | |
629 | case 4: | |
630 | case 8: | |
631 | case 16: | |
632 | break; | |
633 | default: | |
634 | abort(); | |
635 | } | |
636 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_float.offset); | |
637 | memcpy(&value, ptr, float_size_bytes); | |
638 | if (type_visitor->gather_float_type_func) | |
639 | type_visitor->gather_float_type_func(&type_gather->u.side_float, &value, priv); | |
640 | return tracer_gather_size(access_mode, float_size_bytes); | |
641 | } | |
642 | ||
643 | static | |
644 | 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) | |
645 | { | |
646 | ||
647 | enum side_type_gather_access_mode access_mode = | |
648 | (enum side_type_gather_access_mode) type_gather->u.side_string.access_mode; | |
649 | enum side_type_label_byte_order byte_order = side_enum_get(type_gather->u.side_string.type.byte_order); | |
650 | uint8_t unit_size = type_gather->u.side_string.type.unit_size; | |
651 | const char *ptr = (const char *) _ptr; | |
652 | size_t string_len = 0; | |
653 | ||
654 | ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_string.offset); | |
655 | if (ptr) | |
656 | string_len = type_visitor_strlen(ptr, unit_size); | |
657 | if (type_visitor->gather_string_type_func) | |
658 | type_visitor->gather_string_type_func(&type_gather->u.side_string, ptr, unit_size, | |
659 | byte_order, string_len, priv); | |
660 | return tracer_gather_size(access_mode, string_len); | |
661 | } | |
662 | ||
663 | static | |
664 | uint32_t visit_gather_type(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const void *ptr, void *priv) | |
665 | { | |
666 | uint32_t len; | |
667 | ||
668 | switch (side_enum_get(type_desc->type)) { | |
669 | /* Gather basic types */ | |
670 | case SIDE_TYPE_GATHER_BOOL: | |
671 | len = type_visitor_gather_bool(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
672 | break; | |
673 | case SIDE_TYPE_GATHER_INTEGER: | |
674 | len = type_visitor_gather_integer(type_visitor, &type_desc->u.side_gather, ptr, SIDE_TYPE_GATHER_INTEGER, priv); | |
675 | break; | |
676 | case SIDE_TYPE_GATHER_BYTE: | |
677 | len = type_visitor_gather_byte(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
678 | break; | |
679 | case SIDE_TYPE_GATHER_POINTER: | |
680 | len = type_visitor_gather_integer(type_visitor, &type_desc->u.side_gather, ptr, SIDE_TYPE_GATHER_POINTER, priv); | |
681 | break; | |
682 | case SIDE_TYPE_GATHER_FLOAT: | |
683 | len = type_visitor_gather_float(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
684 | break; | |
685 | case SIDE_TYPE_GATHER_STRING: | |
686 | len = type_visitor_gather_string(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
687 | break; | |
688 | ||
689 | /* Gather enumeration types */ | |
690 | case SIDE_TYPE_GATHER_ENUM: | |
691 | len = type_visitor_gather_enum(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
692 | break; | |
693 | ||
694 | /* Gather compound types */ | |
695 | case SIDE_TYPE_GATHER_STRUCT: | |
696 | len = type_visitor_gather_struct(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
697 | break; | |
698 | case SIDE_TYPE_GATHER_ARRAY: | |
699 | len = type_visitor_gather_array(type_visitor, &type_desc->u.side_gather, ptr, priv); | |
700 | break; | |
701 | case SIDE_TYPE_GATHER_VLA: | |
702 | len = type_visitor_gather_vla(type_visitor, &type_desc->u.side_gather, ptr, ptr, priv); | |
703 | break; | |
704 | default: | |
705 | fprintf(stderr, "<UNKNOWN GATHER TYPE>"); | |
706 | abort(); | |
707 | } | |
708 | return len; | |
709 | } | |
710 | ||
711 | static | |
712 | uint32_t visit_gather_elem(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const void *ptr, void *priv) | |
713 | { | |
714 | uint32_t len; | |
715 | ||
716 | if (type_visitor->elem_func) | |
717 | type_visitor->elem_func(SIDE_TYPE_VISITOR_BEFORE, type_desc, priv); | |
718 | len = visit_gather_type(type_visitor, type_desc, ptr, priv); | |
719 | if (type_visitor->elem_func) | |
720 | type_visitor->elem_func(SIDE_TYPE_VISITOR_AFTER, type_desc, priv); | |
721 | return len; | |
722 | } | |
723 | ||
724 | static | |
725 | 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) | |
726 | { | |
727 | const struct side_type *enum_elem_type = side_ptr_get(type_gather->u.side_enum.elem_type); | |
728 | const struct side_type_gather_integer *side_integer = &enum_elem_type->u.side_gather.u.side_integer; | |
729 | enum side_type_gather_access_mode access_mode = | |
730 | (enum side_type_gather_access_mode) side_integer->access_mode; | |
731 | uint32_t integer_size_bytes = side_integer->type.integer_size; | |
732 | const char *ptr = (const char *) _ptr; | |
733 | union side_integer_value value; | |
734 | ||
735 | switch (integer_size_bytes) { | |
736 | case 1: | |
737 | case 2: | |
738 | case 4: | |
739 | case 8: | |
740 | case 16: | |
741 | break; | |
742 | default: | |
743 | abort(); | |
744 | } | |
745 | ptr = tracer_gather_access(access_mode, ptr + side_integer->offset); | |
746 | memcpy(&value, ptr, integer_size_bytes); | |
747 | if (type_visitor->gather_enum_type_func) | |
748 | type_visitor->gather_enum_type_func(&type_gather->u.side_enum, &value, priv); | |
749 | return tracer_gather_size(access_mode, integer_size_bytes); | |
750 | } | |
751 | ||
752 | static | |
753 | void visit_dynamic_field(const struct side_type_visitor *type_visitor, const struct side_arg_dynamic_field *field, void *priv) | |
754 | { | |
755 | if (type_visitor->dynamic_field_func) | |
756 | type_visitor->dynamic_field_func(SIDE_TYPE_VISITOR_BEFORE, field, priv); | |
757 | visit_dynamic_type(type_visitor, &field->elem, priv); | |
758 | if (type_visitor->dynamic_field_func) | |
759 | type_visitor->dynamic_field_func(SIDE_TYPE_VISITOR_AFTER, field, priv); | |
760 | } | |
761 | ||
762 | static | |
763 | void type_visitor_dynamic_struct(const struct side_type_visitor *type_visitor, const struct side_arg_dynamic_struct *dynamic_struct, void *priv) | |
764 | { | |
765 | const struct side_arg_dynamic_field *fields = side_ptr_get(dynamic_struct->fields); | |
766 | uint32_t i, len = dynamic_struct->len; | |
767 | ||
768 | if (type_visitor->dynamic_struct_func) | |
769 | type_visitor->dynamic_struct_func(SIDE_TYPE_VISITOR_BEFORE, dynamic_struct, priv); | |
770 | for (i = 0; i < len; i++) | |
771 | visit_dynamic_field(type_visitor, &fields[i], priv); | |
772 | if (type_visitor->dynamic_struct_func) | |
773 | type_visitor->dynamic_struct_func(SIDE_TYPE_VISITOR_AFTER, dynamic_struct, priv); | |
774 | } | |
775 | ||
776 | struct tracer_dynamic_struct_visitor_priv { | |
777 | const struct side_type_visitor *type_visitor; | |
778 | void *priv; | |
779 | int i; | |
780 | }; | |
781 | ||
782 | static | |
783 | enum side_visitor_status tracer_dynamic_struct_write_elem_cb( | |
784 | const struct side_tracer_dynamic_struct_visitor_ctx *tracer_ctx, | |
785 | const struct side_arg_dynamic_field *dynamic_field) | |
786 | { | |
787 | struct tracer_dynamic_struct_visitor_priv *tracer_priv = | |
788 | (struct tracer_dynamic_struct_visitor_priv *) tracer_ctx->priv; | |
789 | ||
790 | visit_dynamic_field(tracer_priv->type_visitor, dynamic_field, tracer_priv->priv); | |
791 | return SIDE_VISITOR_STATUS_OK; | |
792 | } | |
793 | ||
794 | static | |
795 | void type_visitor_dynamic_struct_visitor(const struct side_type_visitor *type_visitor, const struct side_arg *item, void *priv) | |
796 | { | |
797 | struct side_arg_dynamic_struct_visitor *dynamic_struct_visitor; | |
798 | struct tracer_dynamic_struct_visitor_priv tracer_priv = { | |
799 | .type_visitor = type_visitor, | |
800 | .priv = priv, | |
801 | .i = 0, | |
802 | }; | |
803 | const struct side_tracer_dynamic_struct_visitor_ctx tracer_ctx = { | |
804 | .write_field = tracer_dynamic_struct_write_elem_cb, | |
805 | .priv = &tracer_priv, | |
806 | }; | |
807 | enum side_visitor_status status; | |
808 | void *app_ctx; | |
809 | ||
810 | if (type_visitor->dynamic_struct_visitor_func) | |
811 | type_visitor->dynamic_struct_visitor_func(SIDE_TYPE_VISITOR_BEFORE, item, priv); | |
812 | dynamic_struct_visitor = side_ptr_get(item->u.side_dynamic.side_dynamic_struct_visitor); | |
813 | if (!dynamic_struct_visitor) | |
814 | abort(); | |
815 | app_ctx = side_ptr_get(dynamic_struct_visitor->app_ctx); | |
816 | status = side_ptr_get(dynamic_struct_visitor->visitor)(&tracer_ctx, app_ctx); | |
817 | switch (status) { | |
818 | case SIDE_VISITOR_STATUS_OK: | |
819 | break; | |
820 | case SIDE_VISITOR_STATUS_ERROR: | |
821 | fprintf(stderr, "ERROR: Visitor error\n"); | |
822 | abort(); | |
823 | } | |
824 | if (type_visitor->dynamic_struct_visitor_func) | |
825 | type_visitor->dynamic_struct_visitor_func(SIDE_TYPE_VISITOR_AFTER, item, priv); | |
826 | } | |
827 | ||
828 | static | |
829 | void type_visitor_dynamic_vla(const struct side_type_visitor *type_visitor, const struct side_arg_dynamic_vla *vla, void *priv) | |
830 | { | |
831 | const struct side_arg *sav = side_ptr_get(vla->sav); | |
832 | uint32_t i, side_sav_len = vla->len; | |
833 | ||
834 | if (type_visitor->dynamic_vla_func) | |
835 | type_visitor->dynamic_vla_func(SIDE_TYPE_VISITOR_BEFORE, vla, priv); | |
836 | for (i = 0; i < side_sav_len; i++) | |
837 | visit_dynamic_elem(type_visitor, &sav[i], priv); | |
838 | if (type_visitor->dynamic_vla_func) | |
839 | type_visitor->dynamic_vla_func(SIDE_TYPE_VISITOR_AFTER, vla, priv); | |
840 | } | |
841 | ||
842 | struct tracer_dynamic_vla_visitor_priv { | |
843 | const struct side_type_visitor *type_visitor; | |
844 | void *priv; | |
845 | int i; | |
846 | }; | |
847 | ||
848 | static | |
849 | enum side_visitor_status tracer_dynamic_vla_write_elem_cb( | |
850 | const struct side_tracer_visitor_ctx *tracer_ctx, | |
851 | const struct side_arg *elem) | |
852 | { | |
853 | struct tracer_dynamic_vla_visitor_priv *tracer_priv = | |
854 | (struct tracer_dynamic_vla_visitor_priv *) tracer_ctx->priv; | |
855 | ||
856 | visit_dynamic_elem(tracer_priv->type_visitor, elem, tracer_priv->priv); | |
857 | return SIDE_VISITOR_STATUS_OK; | |
858 | } | |
859 | ||
860 | static | |
861 | void type_visitor_dynamic_vla_visitor(const struct side_type_visitor *type_visitor, const struct side_arg *item, void *priv) | |
862 | { | |
863 | struct side_arg_dynamic_vla_visitor *dynamic_vla_visitor; | |
864 | struct tracer_dynamic_vla_visitor_priv tracer_priv = { | |
865 | .type_visitor = type_visitor, | |
866 | .priv = priv, | |
867 | .i = 0, | |
868 | }; | |
869 | const struct side_tracer_visitor_ctx tracer_ctx = { | |
870 | .write_elem = tracer_dynamic_vla_write_elem_cb, | |
871 | .priv = &tracer_priv, | |
872 | }; | |
873 | enum side_visitor_status status; | |
874 | void *app_ctx; | |
875 | ||
876 | if (type_visitor->dynamic_vla_visitor_func) | |
877 | type_visitor->dynamic_vla_visitor_func(SIDE_TYPE_VISITOR_BEFORE, item, priv); | |
878 | dynamic_vla_visitor = side_ptr_get(item->u.side_dynamic.side_dynamic_vla_visitor); | |
879 | if (!dynamic_vla_visitor) | |
880 | abort(); | |
881 | app_ctx = side_ptr_get(dynamic_vla_visitor->app_ctx); | |
882 | status = side_ptr_get(dynamic_vla_visitor->visitor)(&tracer_ctx, app_ctx); | |
883 | switch (status) { | |
884 | case SIDE_VISITOR_STATUS_OK: | |
885 | break; | |
886 | case SIDE_VISITOR_STATUS_ERROR: | |
887 | fprintf(stderr, "ERROR: Visitor error\n"); | |
888 | abort(); | |
889 | } | |
890 | if (type_visitor->dynamic_vla_visitor_func) | |
891 | type_visitor->dynamic_vla_visitor_func(SIDE_TYPE_VISITOR_AFTER, item, priv); | |
892 | } | |
893 | ||
894 | static | |
895 | void visit_dynamic_type(const struct side_type_visitor *type_visitor, const struct side_arg *dynamic_item, void *priv) | |
896 | { | |
897 | switch (side_enum_get(dynamic_item->type)) { | |
898 | /* Dynamic basic types */ | |
899 | case SIDE_TYPE_DYNAMIC_NULL: | |
900 | if (type_visitor->dynamic_null_func) | |
901 | type_visitor->dynamic_null_func(dynamic_item, priv); | |
902 | break; | |
903 | case SIDE_TYPE_DYNAMIC_BOOL: | |
904 | if (type_visitor->dynamic_bool_func) | |
905 | type_visitor->dynamic_bool_func(dynamic_item, priv); | |
906 | break; | |
907 | case SIDE_TYPE_DYNAMIC_INTEGER: | |
908 | if (type_visitor->dynamic_integer_func) | |
909 | type_visitor->dynamic_integer_func(dynamic_item, priv); | |
910 | break; | |
911 | case SIDE_TYPE_DYNAMIC_BYTE: | |
912 | if (type_visitor->dynamic_byte_func) | |
913 | type_visitor->dynamic_byte_func(dynamic_item, priv); | |
914 | break; | |
915 | case SIDE_TYPE_DYNAMIC_POINTER: | |
916 | if (type_visitor->dynamic_pointer_func) | |
917 | type_visitor->dynamic_pointer_func(dynamic_item, priv); | |
918 | break; | |
919 | case SIDE_TYPE_DYNAMIC_FLOAT: | |
920 | if (type_visitor->dynamic_float_func) | |
921 | type_visitor->dynamic_float_func(dynamic_item, priv); | |
922 | break; | |
923 | case SIDE_TYPE_DYNAMIC_STRING: | |
924 | if (type_visitor->dynamic_string_func) | |
925 | type_visitor->dynamic_string_func(dynamic_item, priv); | |
926 | break; | |
927 | ||
928 | /* Dynamic compound types */ | |
929 | case SIDE_TYPE_DYNAMIC_STRUCT: | |
930 | type_visitor_dynamic_struct(type_visitor, side_ptr_get(dynamic_item->u.side_dynamic.side_dynamic_struct), priv); | |
931 | break; | |
932 | case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR: | |
933 | type_visitor_dynamic_struct_visitor(type_visitor, dynamic_item, priv); | |
934 | break; | |
935 | case SIDE_TYPE_DYNAMIC_VLA: | |
936 | type_visitor_dynamic_vla(type_visitor, side_ptr_get(dynamic_item->u.side_dynamic.side_dynamic_vla), priv); | |
937 | break; | |
938 | case SIDE_TYPE_DYNAMIC_VLA_VISITOR: | |
939 | type_visitor_dynamic_vla_visitor(type_visitor, dynamic_item, priv); | |
940 | break; | |
941 | default: | |
942 | fprintf(stderr, "<UNKNOWN TYPE>\n"); | |
943 | abort(); | |
944 | } | |
945 | } | |
946 | ||
947 | static | |
948 | void visit_dynamic_elem(const struct side_type_visitor *type_visitor, const struct side_arg *dynamic_item, void *priv) | |
949 | { | |
950 | if (type_visitor->elem_func) | |
951 | type_visitor->dynamic_elem_func(SIDE_TYPE_VISITOR_BEFORE, dynamic_item, priv); | |
952 | visit_dynamic_type(type_visitor, dynamic_item, priv); | |
953 | if (type_visitor->elem_func) | |
954 | type_visitor->dynamic_elem_func(SIDE_TYPE_VISITOR_AFTER, dynamic_item, priv); | |
955 | } | |
956 | ||
957 | void side_visit_type(const struct side_type_visitor *type_visitor, const struct side_type *type_desc, const struct side_arg *item, void *priv) | |
958 | { | |
959 | enum side_type_label type; | |
960 | ||
961 | switch (side_enum_get(type_desc->type)) { | |
962 | case SIDE_TYPE_ENUM: | |
963 | switch (side_enum_get(item->type)) { | |
964 | case SIDE_TYPE_U8: | |
965 | case SIDE_TYPE_U16: | |
966 | case SIDE_TYPE_U32: | |
967 | case SIDE_TYPE_U64: | |
968 | case SIDE_TYPE_U128: | |
969 | case SIDE_TYPE_S8: | |
970 | case SIDE_TYPE_S16: | |
971 | case SIDE_TYPE_S32: | |
972 | case SIDE_TYPE_S64: | |
973 | case SIDE_TYPE_S128: | |
974 | break; | |
975 | default: | |
976 | fprintf(stderr, "ERROR: type mismatch between description and arguments\n"); | |
977 | abort(); | |
978 | break; | |
979 | } | |
980 | break; | |
981 | ||
982 | case SIDE_TYPE_ENUM_BITMAP: | |
983 | switch (side_enum_get(item->type)) { | |
984 | case SIDE_TYPE_U8: | |
985 | case SIDE_TYPE_BYTE: | |
986 | case SIDE_TYPE_U16: | |
987 | case SIDE_TYPE_U32: | |
988 | case SIDE_TYPE_U64: | |
989 | case SIDE_TYPE_U128: | |
990 | case SIDE_TYPE_ARRAY: | |
991 | case SIDE_TYPE_VLA: | |
992 | break; | |
993 | default: | |
994 | fprintf(stderr, "ERROR: type mismatch between description and arguments\n"); | |
995 | abort(); | |
996 | break; | |
997 | } | |
998 | break; | |
999 | ||
1000 | case SIDE_TYPE_GATHER_ENUM: | |
1001 | switch (side_enum_get(item->type)) { | |
1002 | case SIDE_TYPE_GATHER_INTEGER: | |
1003 | break; | |
1004 | default: | |
1005 | fprintf(stderr, "ERROR: type mismatch between description and arguments\n"); | |
1006 | abort(); | |
1007 | break; | |
1008 | } | |
1009 | break; | |
1010 | ||
1011 | case SIDE_TYPE_DYNAMIC: | |
1012 | switch (side_enum_get(item->type)) { | |
1013 | case SIDE_TYPE_DYNAMIC_NULL: | |
1014 | case SIDE_TYPE_DYNAMIC_BOOL: | |
1015 | case SIDE_TYPE_DYNAMIC_INTEGER: | |
1016 | case SIDE_TYPE_DYNAMIC_BYTE: | |
1017 | case SIDE_TYPE_DYNAMIC_POINTER: | |
1018 | case SIDE_TYPE_DYNAMIC_FLOAT: | |
1019 | case SIDE_TYPE_DYNAMIC_STRING: | |
1020 | case SIDE_TYPE_DYNAMIC_STRUCT: | |
1021 | case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR: | |
1022 | case SIDE_TYPE_DYNAMIC_VLA: | |
1023 | case SIDE_TYPE_DYNAMIC_VLA_VISITOR: | |
1024 | break; | |
1025 | default: | |
1026 | fprintf(stderr, "ERROR: Unexpected dynamic type\n"); | |
1027 | abort(); | |
1028 | break; | |
1029 | } | |
1030 | break; | |
1031 | ||
1032 | default: | |
1033 | if (side_enum_get(type_desc->type) != side_enum_get(item->type)) { | |
1034 | fprintf(stderr, "ERROR: type mismatch between description and arguments\n"); | |
1035 | abort(); | |
1036 | } | |
1037 | break; | |
1038 | } | |
1039 | ||
1040 | 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) | |
1041 | type = side_enum_get(type_desc->type); | |
1042 | else | |
1043 | type = side_enum_get(item->type); | |
1044 | ||
1045 | switch (type) { | |
1046 | /* Stack-copy basic types */ | |
1047 | case SIDE_TYPE_NULL: | |
1048 | if (type_visitor->null_type_func) | |
1049 | type_visitor->null_type_func(type_desc, item, priv); | |
1050 | break; | |
1051 | case SIDE_TYPE_BOOL: | |
1052 | if (type_visitor->bool_type_func) | |
1053 | type_visitor->bool_type_func(type_desc, item, priv); | |
1054 | break; | |
1055 | case SIDE_TYPE_U8: /* Fallthrough */ | |
1056 | case SIDE_TYPE_U16: /* Fallthrough */ | |
1057 | case SIDE_TYPE_U32: /* Fallthrough */ | |
1058 | case SIDE_TYPE_U64: /* Fallthrough */ | |
1059 | case SIDE_TYPE_U128: /* Fallthrough */ | |
1060 | case SIDE_TYPE_S8: /* Fallthrough */ | |
1061 | case SIDE_TYPE_S16: /* Fallthrough */ | |
1062 | case SIDE_TYPE_S32: /* Fallthrough */ | |
1063 | case SIDE_TYPE_S64: /* Fallthrough */ | |
1064 | case SIDE_TYPE_S128: | |
1065 | if (type_visitor->integer_type_func) | |
1066 | type_visitor->integer_type_func(type_desc, item, priv); | |
1067 | break; | |
1068 | case SIDE_TYPE_BYTE: | |
1069 | if (type_visitor->byte_type_func) | |
1070 | type_visitor->byte_type_func(type_desc, item, priv); | |
1071 | break; | |
1072 | case SIDE_TYPE_POINTER: | |
1073 | if (type_visitor->pointer_type_func) | |
1074 | type_visitor->pointer_type_func(type_desc, item, priv); | |
1075 | break; | |
1076 | case SIDE_TYPE_FLOAT_BINARY16: /* Fallthrough */ | |
1077 | case SIDE_TYPE_FLOAT_BINARY32: /* Fallthrough */ | |
1078 | case SIDE_TYPE_FLOAT_BINARY64: /* Fallthrough */ | |
1079 | case SIDE_TYPE_FLOAT_BINARY128: | |
1080 | if (type_visitor->float_type_func) | |
1081 | type_visitor->float_type_func(type_desc, item, priv); | |
1082 | break; | |
1083 | case SIDE_TYPE_STRING_UTF8: /* Fallthrough */ | |
1084 | case SIDE_TYPE_STRING_UTF16: /* Fallthrough */ | |
1085 | case SIDE_TYPE_STRING_UTF32: | |
1086 | if (type_visitor->string_type_func) | |
1087 | type_visitor->string_type_func(type_desc, item, priv); | |
1088 | break; | |
1089 | case SIDE_TYPE_ENUM: | |
1090 | if (type_visitor->enum_type_func) | |
1091 | type_visitor->enum_type_func(type_desc, item, priv); | |
1092 | break; | |
1093 | case SIDE_TYPE_ENUM_BITMAP: | |
1094 | if (type_visitor->enum_bitmap_type_func) | |
1095 | type_visitor->enum_bitmap_type_func(type_desc, item, priv); | |
1096 | break; | |
1097 | ||
1098 | /* Stack-copy compound types */ | |
1099 | case SIDE_TYPE_STRUCT: | |
1100 | type_visitor_struct(type_visitor, type_desc, side_ptr_get(item->u.side_static.side_struct), priv); | |
1101 | break; | |
1102 | case SIDE_TYPE_VARIANT: | |
1103 | type_visitor_variant(type_visitor, type_desc, side_ptr_get(item->u.side_static.side_variant), priv); | |
1104 | break; | |
1105 | case SIDE_TYPE_ARRAY: | |
1106 | type_visitor_array(type_visitor, type_desc, side_ptr_get(item->u.side_static.side_array), priv); | |
1107 | break; | |
1108 | case SIDE_TYPE_VLA: | |
1109 | type_visitor_vla(type_visitor, type_desc, side_ptr_get(item->u.side_static.side_vla), priv); | |
1110 | break; | |
1111 | case SIDE_TYPE_VLA_VISITOR: | |
1112 | type_visitor_vla_visitor(type_visitor, type_desc, side_ptr_get(item->u.side_static.side_vla_visitor), priv); | |
1113 | break; | |
1114 | ||
1115 | /* Gather basic types */ | |
1116 | case SIDE_TYPE_GATHER_BOOL: | |
1117 | (void) type_visitor_gather_bool(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_bool_gather_ptr), priv); | |
1118 | break; | |
1119 | case SIDE_TYPE_GATHER_INTEGER: | |
1120 | (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); | |
1121 | break; | |
1122 | case SIDE_TYPE_GATHER_BYTE: | |
1123 | (void) type_visitor_gather_byte(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_byte_gather_ptr), priv); | |
1124 | break; | |
1125 | case SIDE_TYPE_GATHER_POINTER: | |
1126 | (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); | |
1127 | break; | |
1128 | case SIDE_TYPE_GATHER_FLOAT: | |
1129 | (void) type_visitor_gather_float(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_float_gather_ptr), priv); | |
1130 | break; | |
1131 | case SIDE_TYPE_GATHER_STRING: | |
1132 | (void) type_visitor_gather_string(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_string_gather_ptr), priv); | |
1133 | break; | |
1134 | ||
1135 | /* Gather compound type */ | |
1136 | case SIDE_TYPE_GATHER_STRUCT: | |
1137 | (void) type_visitor_gather_struct(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_struct_gather_ptr), priv); | |
1138 | break; | |
1139 | case SIDE_TYPE_GATHER_ARRAY: | |
1140 | (void) type_visitor_gather_array(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_array_gather_ptr), priv); | |
1141 | break; | |
1142 | case SIDE_TYPE_GATHER_VLA: | |
1143 | (void) type_visitor_gather_vla(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_array_gather_ptr), | |
1144 | side_ptr_get(item->u.side_static.side_vla_gather.length_ptr), priv); | |
1145 | break; | |
1146 | ||
1147 | /* Gather enumeration types */ | |
1148 | case SIDE_TYPE_GATHER_ENUM: | |
1149 | (void) type_visitor_gather_enum(type_visitor, &type_desc->u.side_gather, side_ptr_get(item->u.side_static.side_integer_gather_ptr), priv); | |
1150 | break; | |
1151 | ||
1152 | /* Dynamic basic types */ | |
1153 | case SIDE_TYPE_DYNAMIC_NULL: /* Fallthrough */ | |
1154 | case SIDE_TYPE_DYNAMIC_BOOL: /* Fallthrough */ | |
1155 | case SIDE_TYPE_DYNAMIC_INTEGER: /* Fallthrough */ | |
1156 | case SIDE_TYPE_DYNAMIC_BYTE: /* Fallthrough */ | |
1157 | case SIDE_TYPE_DYNAMIC_POINTER: /* Fallthrough */ | |
1158 | case SIDE_TYPE_DYNAMIC_FLOAT: /* Fallthrough */ | |
1159 | case SIDE_TYPE_DYNAMIC_STRING: /* Fallthrough */ | |
1160 | ||
1161 | /* Dynamic compound types */ | |
1162 | case SIDE_TYPE_DYNAMIC_STRUCT: /* Fallthrough */ | |
1163 | case SIDE_TYPE_DYNAMIC_STRUCT_VISITOR: /* Fallthrough */ | |
1164 | case SIDE_TYPE_DYNAMIC_VLA: /* Fallthrough */ | |
1165 | case SIDE_TYPE_DYNAMIC_VLA_VISITOR: | |
1166 | visit_dynamic_type(type_visitor, item, priv); | |
1167 | break; | |
1168 | ||
1169 | default: | |
1170 | fprintf(stderr, "<UNKNOWN TYPE>\n"); | |
1171 | abort(); | |
1172 | } | |
1173 | } | |
1174 | ||
1175 | void type_visitor_event(const struct side_type_visitor *type_visitor, | |
1176 | const struct side_event_description *desc, | |
1177 | const struct side_arg_vec *side_arg_vec, | |
1178 | const struct side_arg_dynamic_struct *var_struct, | |
1179 | void *caller_addr, void *priv) | |
1180 | { | |
1181 | const struct side_arg *sav = side_ptr_get(side_arg_vec->sav); | |
1182 | uint32_t i, side_sav_len = side_arg_vec->len; | |
1183 | ||
1184 | if (desc->nr_fields != side_sav_len) { | |
1185 | fprintf(stderr, "ERROR: number of fields mismatch between description and arguments\n"); | |
1186 | abort(); | |
1187 | } | |
1188 | if (type_visitor->event_func) | |
1189 | type_visitor->event_func(SIDE_TYPE_VISITOR_BEFORE, desc, side_arg_vec, var_struct, caller_addr, priv); | |
1190 | if (side_sav_len) { | |
1191 | if (type_visitor->static_fields_func) | |
1192 | type_visitor->static_fields_func(SIDE_TYPE_VISITOR_BEFORE, side_arg_vec, priv); | |
1193 | for (i = 0; i < side_sav_len; i++) | |
1194 | side_visit_field(type_visitor, &side_ptr_get(desc->fields)[i], &sav[i], priv); | |
1195 | if (type_visitor->static_fields_func) | |
1196 | type_visitor->static_fields_func(SIDE_TYPE_VISITOR_AFTER, side_arg_vec, priv); | |
1197 | } | |
1198 | if (var_struct) { | |
1199 | uint32_t var_struct_len = var_struct->len; | |
1200 | ||
1201 | if (type_visitor->variadic_fields_func) | |
1202 | type_visitor->variadic_fields_func(SIDE_TYPE_VISITOR_BEFORE, var_struct, priv); | |
1203 | for (i = 0; i < var_struct_len; i++) | |
1204 | visit_dynamic_field(type_visitor, &side_ptr_get(var_struct->fields)[i], priv); | |
1205 | if (type_visitor->variadic_fields_func) | |
1206 | type_visitor->variadic_fields_func(SIDE_TYPE_VISITOR_AFTER, var_struct, priv); | |
1207 | } | |
1208 | if (type_visitor->event_func) | |
1209 | type_visitor->event_func(SIDE_TYPE_VISITOR_AFTER, desc, side_arg_vec, var_struct, caller_addr, priv); | |
1210 | } |