41d7410cb97eca8f17b595aae42f03407ad32803
[babeltrace.git] / src / plugins / ctf / common / src / metadata / tsdl / visitor-generate-ir.cpp
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * Copyright 2015-2018 Philippe Proulx <philippe.proulx@efficios.com>
6 *
7 * Common Trace Format metadata visitor (generates CTF IR objects).
8 */
9
10 #include <stdio.h>
11 #include <string.h>
12
13 #include "logging.hpp"
14
15 #include "common/assert.h"
16 #include "common/common.h"
17 #include "common/uuid.h"
18 #include "compat/endian.h" /* IWYU pragma: keep */
19 #include "cpp-common/bt2c/logging.hpp"
20
21 #include "ast.hpp"
22 #include "ctf-meta-visitors.hpp"
23
24 /* Bit value (left shift) */
25 #define _BV(_val) (1 << (_val))
26
27 /* Bit is set in a set of bits */
28 #define _IS_SET(_set, _mask) (*(_set) & (_mask))
29
30 /* Set bit in a set of bits */
31 #define _SET(_set, _mask) (*(_set) |= (_mask))
32
33 /* Try to push scope, or go to the `error` label */
34 #define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
35 do { \
36 ret = ctx_push_scope(ctx); \
37 if (ret) { \
38 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger, "Cannot push scope."); \
39 goto error; \
40 } \
41 } while (0)
42
43 /* Bits for verifying existing attributes in various declarations */
44 enum
45 {
46 _CLOCK_NAME_SET = _BV(0),
47 _CLOCK_UUID_SET = _BV(1),
48 _CLOCK_FREQ_SET = _BV(2),
49 _CLOCK_PRECISION_SET = _BV(3),
50 _CLOCK_OFFSET_S_SET = _BV(4),
51 _CLOCK_OFFSET_SET = _BV(5),
52 _CLOCK_ABSOLUTE_SET = _BV(6),
53 _CLOCK_DESCRIPTION_SET = _BV(7),
54 };
55
56 enum
57 {
58 _INTEGER_ALIGN_SET = _BV(0),
59 _INTEGER_SIZE_SET = _BV(1),
60 _INTEGER_BASE_SET = _BV(2),
61 _INTEGER_ENCODING_SET = _BV(3),
62 _INTEGER_BYTE_ORDER_SET = _BV(4),
63 _INTEGER_SIGNED_SET = _BV(5),
64 _INTEGER_MAP_SET = _BV(6),
65 };
66
67 enum
68 {
69 _FLOAT_ALIGN_SET = _BV(0),
70 _FLOAT_MANT_DIG_SET = _BV(1),
71 _FLOAT_EXP_DIG_SET = _BV(2),
72 _FLOAT_BYTE_ORDER_SET = _BV(3),
73 };
74
75 enum
76 {
77 _STRING_ENCODING_SET = _BV(0),
78 };
79
80 enum
81 {
82 _TRACE_MINOR_SET = _BV(0),
83 _TRACE_MAJOR_SET = _BV(1),
84 _TRACE_BYTE_ORDER_SET = _BV(2),
85 _TRACE_UUID_SET = _BV(3),
86 _TRACE_PACKET_HEADER_SET = _BV(4),
87 };
88
89 enum
90 {
91 _STREAM_ID_SET = _BV(0),
92 _STREAM_PACKET_CONTEXT_SET = _BV(1),
93 _STREAM_EVENT_HEADER_SET = _BV(2),
94 _STREAM_EVENT_CONTEXT_SET = _BV(3),
95 };
96
97 enum
98 {
99 _EVENT_NAME_SET = _BV(0),
100 _EVENT_ID_SET = _BV(1),
101 _EVENT_MODEL_EMF_URI_SET = _BV(2),
102 _EVENT_STREAM_ID_SET = _BV(3),
103 _EVENT_LOG_LEVEL_SET = _BV(4),
104 _EVENT_CONTEXT_SET = _BV(5),
105 _EVENT_FIELDS_SET = _BV(6),
106 };
107
108 enum loglevel
109 {
110 LOG_LEVEL_EMERG = 0,
111 LOG_LEVEL_ALERT = 1,
112 LOG_LEVEL_CRIT = 2,
113 LOG_LEVEL_ERR = 3,
114 LOG_LEVEL_WARNING = 4,
115 LOG_LEVEL_NOTICE = 5,
116 LOG_LEVEL_INFO = 6,
117 LOG_LEVEL_DEBUG_SYSTEM = 7,
118 LOG_LEVEL_DEBUG_PROGRAM = 8,
119 LOG_LEVEL_DEBUG_PROCESS = 9,
120 LOG_LEVEL_DEBUG_MODULE = 10,
121 LOG_LEVEL_DEBUG_UNIT = 11,
122 LOG_LEVEL_DEBUG_FUNCTION = 12,
123 LOG_LEVEL_DEBUG_LINE = 13,
124 LOG_LEVEL_DEBUG = 14,
125 _NR_LOGLEVELS = 15,
126 };
127
128 /* Prefixes of class aliases */
129 #define _PREFIX_ALIAS 'a'
130 #define _PREFIX_ENUM 'e'
131 #define _PREFIX_STRUCT 's'
132 #define _PREFIX_VARIANT 'v'
133
134 /* First entry in a BT list */
135 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) bt_list_entry((_ptr)->next, _class, _member)
136
137 #define _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \
138 _BT_CPPLOGE_APPEND_CAUSE_LINENO(ctx->logger, (_node)->lineno, \
139 "Duplicate attribute in {}: attr-name=\"{}\"", _entity, _attr)
140
141 #define _BT_CPPLOGE_NODE(_node, _msg, args...) \
142 _BT_CPPLOGE_LINENO(ctx->logger, (_node)->lineno, _msg, ##args)
143
144 #define _BT_CPPLOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
145 _BT_CPPLOGE_APPEND_CAUSE_LINENO(ctx->logger, (_node)->lineno, _msg, ##args)
146
147 #define _BT_CPPLOGW_NODE(_node, _msg, args...) \
148 _BT_CPPLOGW_LINENO(ctx->logger, (_node)->lineno, _msg, ##args)
149
150 #define _BT_CPPLOGT_NODE(_node, _msg, args...) \
151 _BT_CPPLOGT_LINENO(ctx->logger, (_node)->lineno, _msg, ##args)
152
153 /*
154 * Declaration scope of a visitor context. This represents a TSDL
155 * lexical scope, so that aliases and named structures, variants,
156 * and enumerations may be registered and looked up hierarchically.
157 */
158 struct ctx_decl_scope
159 {
160 /*
161 * Alias name to field class.
162 *
163 * GQuark -> struct ctf_field_class * (owned by this)
164 */
165 GHashTable *decl_map;
166
167 /* Parent scope; NULL if this is the root declaration scope */
168 struct ctx_decl_scope *parent_scope;
169 };
170
171 /**
172 * Creates a new declaration scope.
173 *
174 * @param par_scope Parent scope (NULL if creating a root scope)
175 * @returns New declaration scope, or NULL on error
176 */
177 static struct ctx_decl_scope *ctx_decl_scope_create(struct ctf_visitor_generate_ir *ctx,
178 struct ctx_decl_scope *par_scope)
179 {
180 struct ctx_decl_scope *scope;
181
182 scope = g_new(struct ctx_decl_scope, 1);
183 if (!scope) {
184 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger, "Failed to allocate one declaration scope.");
185 goto end;
186 }
187
188 scope->decl_map = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
189 (GDestroyNotify) ctf_field_class_destroy);
190 scope->parent_scope = par_scope;
191
192 end:
193 return scope;
194 }
195
196 /**
197 * Destroys a declaration scope.
198 *
199 * This function does not destroy the parent scope.
200 *
201 * @param scope Scope to destroy
202 */
203 static void ctx_decl_scope_destroy(struct ctx_decl_scope *scope)
204 {
205 if (!scope) {
206 goto end;
207 }
208
209 g_hash_table_destroy(scope->decl_map);
210 g_free(scope);
211
212 end:
213 return;
214 }
215
216 /**
217 * Returns the GQuark of a prefixed alias.
218 *
219 * @param prefix Prefix character
220 * @param name Name
221 * @returns Associated GQuark, or 0 on error
222 */
223 static GQuark get_prefixed_named_quark(char prefix, const char *name)
224 {
225 BT_ASSERT(name);
226 std::string prname = std::string {prefix} + name;
227 return g_quark_from_string(prname.c_str());
228 }
229
230 /**
231 * Looks up a prefixed class alias within a declaration scope.
232 *
233 * @param scope Declaration scope
234 * @param prefix Prefix character
235 * @param name Alias name
236 * @param levels Number of levels to dig into (-1 means infinite)
237 * @param copy True to return a copy
238 * @returns Declaration (owned by caller if \p copy is true),
239 * or NULL if not found
240 */
241 static struct ctf_field_class *ctx_decl_scope_lookup_prefix_alias(struct ctx_decl_scope *scope,
242 char prefix, const char *name,
243 int levels, bool copy)
244 {
245 GQuark qname = 0;
246 int cur_levels = 0;
247 struct ctf_field_class *decl = NULL;
248 struct ctx_decl_scope *cur_scope = scope;
249
250 BT_ASSERT(scope);
251 BT_ASSERT(name);
252 qname = get_prefixed_named_quark(prefix, name);
253 if (!qname) {
254 goto end;
255 }
256
257 if (levels < 0) {
258 levels = INT_MAX;
259 }
260
261 while (cur_scope && cur_levels < levels) {
262 decl = (ctf_field_class *) g_hash_table_lookup(cur_scope->decl_map,
263 (gconstpointer) GUINT_TO_POINTER(qname));
264 if (decl) {
265 /* Caller's reference */
266 if (copy) {
267 decl = ctf_field_class_copy(decl);
268 BT_ASSERT(decl);
269 }
270
271 goto end;
272 }
273
274 cur_scope = cur_scope->parent_scope;
275 cur_levels++;
276 }
277
278 end:
279 return decl;
280 }
281
282 /**
283 * Looks up a class alias within a declaration scope.
284 *
285 * @param scope Declaration scope
286 * @param name Alias name
287 * @param levels Number of levels to dig into (-1 means infinite)
288 * @param copy True to return a copy
289 * @returns Declaration (owned by caller if \p copy is true),
290 * or NULL if not found
291 */
292 static struct ctf_field_class *ctx_decl_scope_lookup_alias(struct ctx_decl_scope *scope,
293 const char *name, int levels, bool copy)
294 {
295 return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ALIAS, name, levels, copy);
296 }
297
298 /**
299 * Looks up an enumeration within a declaration scope.
300 *
301 * @param scope Declaration scope
302 * @param name Enumeration name
303 * @param levels Number of levels to dig into (-1 means infinite)
304 * @param copy True to return a copy
305 * @returns Declaration (owned by caller if \p copy is true),
306 * or NULL if not found
307 */
308 static struct ctf_field_class_enum *
309 ctx_decl_scope_lookup_enum(struct ctx_decl_scope *scope, const char *name, int levels, bool copy)
310 {
311 return ctf_field_class_as_enum(
312 ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ENUM, name, levels, copy));
313 }
314
315 /**
316 * Looks up a structure within a declaration scope.
317 *
318 * @param scope Declaration scope
319 * @param name Structure name
320 * @param levels Number of levels to dig into (-1 means infinite)
321 * @param copy True to return a copy
322 * @returns Declaration (owned by caller if \p copy is true),
323 * or NULL if not found
324 */
325 static struct ctf_field_class_struct *
326 ctx_decl_scope_lookup_struct(struct ctx_decl_scope *scope, const char *name, int levels, bool copy)
327 {
328 return ctf_field_class_as_struct(
329 ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_STRUCT, name, levels, copy));
330 }
331
332 /**
333 * Looks up a variant within a declaration scope.
334 *
335 * @param scope Declaration scope
336 * @param name Variant name
337 * @param levels Number of levels to dig into (-1 means infinite)
338 * @param copy True to return a copy
339 * @returns Declaration (owned by caller if \p copy is true),
340 * or NULL if not found
341 */
342 static struct ctf_field_class_variant *
343 ctx_decl_scope_lookup_variant(struct ctx_decl_scope *scope, const char *name, int levels, bool copy)
344 {
345 return ctf_field_class_as_variant(
346 ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_VARIANT, name, levels, copy));
347 }
348
349 /**
350 * Registers a prefixed class alias within a declaration scope.
351 *
352 * @param scope Declaration scope
353 * @param prefix Prefix character
354 * @param name Alias name (non-NULL)
355 * @param decl Field class to register (copied)
356 * @returns 0 if registration went okay, negative value otherwise
357 */
358 static int ctx_decl_scope_register_prefix_alias(struct ctx_decl_scope *scope, char prefix,
359 const char *name, struct ctf_field_class *decl)
360 {
361 int ret = 0;
362 GQuark qname = 0;
363
364 BT_ASSERT(scope);
365 BT_ASSERT(name);
366 BT_ASSERT(decl);
367 qname = get_prefixed_named_quark(prefix, name);
368 if (!qname) {
369 ret = -ENOMEM;
370 goto end;
371 }
372
373 /* Make sure alias does not exist in local scope */
374 if (ctx_decl_scope_lookup_prefix_alias(scope, prefix, name, 1, false)) {
375 ret = -EEXIST;
376 goto end;
377 }
378
379 decl = ctf_field_class_copy(decl);
380 BT_ASSERT(decl);
381 g_hash_table_insert(scope->decl_map, GUINT_TO_POINTER(qname), decl);
382
383 end:
384 return ret;
385 }
386
387 /**
388 * Registers a class alias within a declaration scope.
389 *
390 * @param scope Declaration scope
391 * @param name Alias name (non-NULL)
392 * @param decl Field class to register (copied)
393 * @returns 0 if registration went okay, negative value otherwise
394 */
395 static int ctx_decl_scope_register_alias(struct ctx_decl_scope *scope, const char *name,
396 struct ctf_field_class *decl)
397 {
398 return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_ALIAS, name, decl);
399 }
400
401 /**
402 * Registers an enumeration declaration within a declaration scope.
403 *
404 * @param scope Declaration scope
405 * @param name Enumeration name (non-NULL)
406 * @param decl Enumeration field class to register (copied)
407 * @returns 0 if registration went okay, negative value otherwise
408 */
409 static int ctx_decl_scope_register_enum(struct ctx_decl_scope *scope, const char *name,
410 struct ctf_field_class_enum *decl)
411 {
412 return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_ENUM, name, &decl->base.base.base);
413 }
414
415 /**
416 * Registers a structure declaration within a declaration scope.
417 *
418 * @param scope Declaration scope
419 * @param name Structure name (non-NULL)
420 * @param decl Structure field class to register (copied)
421 * @returns 0 if registration went okay, negative value otherwise
422 */
423 static int ctx_decl_scope_register_struct(struct ctx_decl_scope *scope, const char *name,
424 struct ctf_field_class_struct *decl)
425 {
426 return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_STRUCT, name, &decl->base);
427 }
428
429 /**
430 * Registers a variant declaration within a declaration scope.
431 *
432 * @param scope Declaration scope
433 * @param name Variant name (non-NULL)
434 * @param decl Variant field class to register
435 * @returns 0 if registration went okay, negative value otherwise
436 */
437 static int ctx_decl_scope_register_variant(struct ctx_decl_scope *scope, const char *name,
438 struct ctf_field_class_variant *decl)
439 {
440 return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_VARIANT, name, &decl->base);
441 }
442
443 /**
444 * Destroys a visitor context.
445 *
446 * @param ctx Visitor context to destroy
447 */
448 static void ctx_destroy(struct ctf_visitor_generate_ir *ctx)
449 {
450 struct ctx_decl_scope *scope;
451
452 if (!ctx) {
453 goto end;
454 }
455
456 scope = ctx->current_scope;
457
458 /*
459 * Destroy all scopes, from current one to the root scope.
460 */
461 while (scope) {
462 struct ctx_decl_scope *parent_scope = scope->parent_scope;
463
464 ctx_decl_scope_destroy(scope);
465 scope = parent_scope;
466 }
467
468 bt_trace_class_put_ref(ctx->trace_class);
469
470 if (ctx->ctf_tc) {
471 ctf_trace_class_destroy(ctx->ctf_tc);
472 }
473
474 delete ctx;
475
476 end:
477 return;
478 }
479
480 /**
481 * Creates a new visitor context.
482 *
483 * @param trace Associated trace
484 * @returns New visitor context, or NULL on error
485 */
486 static struct ctf_visitor_generate_ir *
487 ctx_create(const struct ctf_metadata_decoder_config *decoder_config, const bt2c::Logger& logger)
488 {
489 BT_ASSERT(decoder_config);
490
491 ctf_visitor_generate_ir *ctx = new ctf_visitor_generate_ir {*decoder_config, logger};
492
493 if (decoder_config->self_comp) {
494 ctx->trace_class = bt_trace_class_create(decoder_config->self_comp);
495 if (!ctx->trace_class) {
496 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger, "Cannot create empty trace class.");
497 goto error;
498 }
499 }
500
501 ctx->ctf_tc = ctf_trace_class_create();
502 if (!ctx->ctf_tc) {
503 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger, "Cannot create CTF trace class.");
504 goto error;
505 }
506
507 /* Root declaration scope */
508 ctx->current_scope = ctx_decl_scope_create(ctx, NULL);
509 if (!ctx->current_scope) {
510 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger, "Cannot create declaration scope.");
511 goto error;
512 }
513
514 goto end;
515
516 error:
517 ctx_destroy(ctx);
518 ctx = NULL;
519
520 end:
521 return ctx;
522 }
523
524 /**
525 * Pushes a new declaration scope on top of a visitor context's
526 * declaration scope stack.
527 *
528 * @param ctx Visitor context
529 * @returns 0 on success, or a negative value on error
530 */
531 static int ctx_push_scope(struct ctf_visitor_generate_ir *ctx)
532 {
533 int ret = 0;
534 struct ctx_decl_scope *new_scope;
535
536 BT_ASSERT(ctx);
537 new_scope = ctx_decl_scope_create(ctx, ctx->current_scope);
538 if (!new_scope) {
539 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger, "Cannot create declaration scope.");
540 ret = -ENOMEM;
541 goto end;
542 }
543
544 ctx->current_scope = new_scope;
545
546 end:
547 return ret;
548 }
549
550 static void ctx_pop_scope(struct ctf_visitor_generate_ir *ctx)
551 {
552 struct ctx_decl_scope *parent_scope = NULL;
553
554 BT_ASSERT(ctx);
555
556 if (!ctx->current_scope) {
557 goto end;
558 }
559
560 parent_scope = ctx->current_scope->parent_scope;
561 ctx_decl_scope_destroy(ctx->current_scope);
562 ctx->current_scope = parent_scope;
563
564 end:
565 return;
566 }
567
568 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir *ctx,
569 struct ctf_node *ts_list,
570 struct ctf_field_class **decl);
571
572 static int is_unary_string(struct bt_list_head *head)
573 {
574 int ret = TRUE;
575 struct ctf_node *node;
576
577 bt_list_for_each_entry (node, head, siblings) {
578 if (node->type != NODE_UNARY_EXPRESSION) {
579 ret = FALSE;
580 }
581
582 if (node->u.unary_expression.type != UNARY_STRING) {
583 ret = FALSE;
584 }
585 }
586
587 return ret;
588 }
589
590 static const char *get_map_clock_name_value(struct bt_list_head *head)
591 {
592 int i = 0;
593 struct ctf_node *node;
594 const char *name = NULL;
595
596 bt_list_for_each_entry (node, head, siblings) {
597 char *src_string;
598 int uexpr_type = node->u.unary_expression.type;
599 int uexpr_link = node->u.unary_expression.link;
600 int cond = node->type != NODE_UNARY_EXPRESSION || uexpr_type != UNARY_STRING ||
601 !((uexpr_link != UNARY_LINK_UNKNOWN) ^ (i == 0));
602 if (cond) {
603 goto error;
604 }
605
606 /* Needs to be chained with . */
607 switch (node->u.unary_expression.link) {
608 case UNARY_DOTLINK:
609 break;
610 case UNARY_ARROWLINK:
611 case UNARY_DOTDOTDOT:
612 goto error;
613 default:
614 break;
615 }
616
617 src_string = node->u.unary_expression.u.string;
618
619 switch (i) {
620 case 0:
621 if (strcmp("clock", src_string)) {
622 goto error;
623 }
624 break;
625 case 1:
626 name = src_string;
627 break;
628 case 2:
629 if (strcmp("value", src_string)) {
630 goto error;
631 }
632 break;
633 default:
634 /* Extra identifier, unknown */
635 goto error;
636 }
637
638 i++;
639 }
640
641 return name;
642
643 error:
644 return NULL;
645 }
646
647 static int is_unary_unsigned(struct bt_list_head *head)
648 {
649 int ret = TRUE;
650 struct ctf_node *node;
651
652 bt_list_for_each_entry (node, head, siblings) {
653 if (node->type != NODE_UNARY_EXPRESSION) {
654 ret = FALSE;
655 }
656
657 if (node->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
658 ret = FALSE;
659 }
660 }
661
662 return ret;
663 }
664
665 static int get_unary_unsigned(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *head,
666 uint64_t *value)
667 {
668 int i = 0;
669 int ret = 0;
670 struct ctf_node *node;
671
672 *value = 0;
673
674 if (bt_list_empty(head)) {
675 ret = -1;
676 goto end;
677 }
678
679 bt_list_for_each_entry (node, head, siblings) {
680 int uexpr_type = node->u.unary_expression.type;
681 int uexpr_link = node->u.unary_expression.link;
682 int cond = node->type != NODE_UNARY_EXPRESSION || uexpr_type != UNARY_UNSIGNED_CONSTANT ||
683 uexpr_link != UNARY_LINK_UNKNOWN || i != 0;
684 if (cond) {
685 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Invalid constant unsigned integer.");
686 ret = -EINVAL;
687 goto end;
688 }
689
690 *value = node->u.unary_expression.u.unsigned_constant;
691 i++;
692 }
693
694 end:
695 return ret;
696 }
697
698 static int is_unary_signed(struct bt_list_head *head)
699 {
700 int ret = TRUE;
701 struct ctf_node *node;
702
703 bt_list_for_each_entry (node, head, siblings) {
704 if (node->type != NODE_UNARY_EXPRESSION) {
705 ret = FALSE;
706 }
707
708 if (node->u.unary_expression.type != UNARY_SIGNED_CONSTANT) {
709 ret = FALSE;
710 }
711 }
712
713 return ret;
714 }
715
716 static int get_unary_signed(struct bt_list_head *head, int64_t *value)
717 {
718 int i = 0;
719 int ret = 0;
720 struct ctf_node *node;
721
722 bt_list_for_each_entry (node, head, siblings) {
723 int uexpr_type = node->u.unary_expression.type;
724 int uexpr_link = node->u.unary_expression.link;
725 int cond = node->type != NODE_UNARY_EXPRESSION ||
726 (uexpr_type != UNARY_UNSIGNED_CONSTANT && uexpr_type != UNARY_SIGNED_CONSTANT) ||
727 uexpr_link != UNARY_LINK_UNKNOWN || i != 0;
728 if (cond) {
729 ret = -EINVAL;
730 goto end;
731 }
732
733 switch (uexpr_type) {
734 case UNARY_UNSIGNED_CONSTANT:
735 *value = (int64_t) node->u.unary_expression.u.unsigned_constant;
736 break;
737 case UNARY_SIGNED_CONSTANT:
738 *value = node->u.unary_expression.u.signed_constant;
739 break;
740 default:
741 ret = -EINVAL;
742 goto end;
743 }
744
745 i++;
746 }
747
748 end:
749 return ret;
750 }
751
752 static int get_unary_uuid(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *head,
753 bt_uuid_t uuid)
754 {
755 return ctf_ast_get_unary_uuid(head, uuid, ctx->logger);
756 }
757
758 static int get_boolean(struct ctf_visitor_generate_ir *ctx, struct ctf_node *unary_expr)
759 {
760 int ret = 0;
761
762 if (unary_expr->type != NODE_UNARY_EXPRESSION) {
763 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr, "Expecting unary expression: node-type={}",
764 unary_expr->type);
765 ret = -EINVAL;
766 goto end;
767 }
768
769 switch (unary_expr->u.unary_expression.type) {
770 case UNARY_UNSIGNED_CONSTANT:
771 ret = (unary_expr->u.unary_expression.u.unsigned_constant != 0);
772 break;
773 case UNARY_SIGNED_CONSTANT:
774 ret = (unary_expr->u.unary_expression.u.signed_constant != 0);
775 break;
776 case UNARY_STRING:
777 {
778 const char *str = unary_expr->u.unary_expression.u.string;
779
780 if (strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0) {
781 ret = TRUE;
782 } else if (strcmp(str, "false") == 0 || strcmp(str, "FALSE") == 0) {
783 ret = FALSE;
784 } else {
785 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr, "Unexpected boolean value: value=\"{}\"",
786 str);
787 ret = -EINVAL;
788 goto end;
789 }
790 break;
791 }
792 default:
793 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr, "Unexpected unary expression type: node-type={}",
794 unary_expr->u.unary_expression.type);
795 ret = -EINVAL;
796 goto end;
797 }
798
799 end:
800 return ret;
801 }
802
803 static enum ctf_byte_order byte_order_from_unary_expr(struct ctf_visitor_generate_ir *ctx,
804 struct ctf_node *unary_expr)
805 {
806 const char *str;
807 enum ctf_byte_order bo = CTF_BYTE_ORDER_UNKNOWN;
808
809 if (unary_expr->u.unary_expression.type != UNARY_STRING) {
810 _BT_CPPLOGE_APPEND_CAUSE_NODE(
811 unary_expr, "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
812 goto end;
813 }
814
815 str = unary_expr->u.unary_expression.u.string;
816
817 if (strcmp(str, "be") == 0 || strcmp(str, "network") == 0) {
818 bo = CTF_BYTE_ORDER_BIG;
819 } else if (strcmp(str, "le") == 0) {
820 bo = CTF_BYTE_ORDER_LITTLE;
821 } else if (strcmp(str, "native") == 0) {
822 bo = CTF_BYTE_ORDER_DEFAULT;
823 } else {
824 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr,
825 "Unexpected \"byte_order\" attribute value: "
826 "expecting `be`, `le`, `network`, or `native`: value=\"{}\"",
827 str);
828 goto end;
829 }
830
831 end:
832 return bo;
833 }
834
835 static enum ctf_byte_order get_real_byte_order(struct ctf_visitor_generate_ir *ctx,
836 struct ctf_node *uexpr)
837 {
838 enum ctf_byte_order bo = byte_order_from_unary_expr(ctx, uexpr);
839
840 if (bo == CTF_BYTE_ORDER_DEFAULT) {
841 bo = ctx->ctf_tc->default_byte_order;
842 }
843
844 return bo;
845 }
846
847 static int is_align_valid(uint64_t align)
848 {
849 return (align != 0) && !(align & (align - UINT64_C(1)));
850 }
851
852 static int get_class_specifier_name(struct ctf_visitor_generate_ir *ctx,
853 struct ctf_node *cls_specifier, GString *str)
854 {
855 int ret = 0;
856
857 if (cls_specifier->type != NODE_TYPE_SPECIFIER) {
858 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier, "Unexpected node type: node-type={}",
859 cls_specifier->type);
860 ret = -EINVAL;
861 goto end;
862 }
863
864 switch (cls_specifier->u.field_class_specifier.type) {
865 case TYPESPEC_VOID:
866 g_string_append(str, "void");
867 break;
868 case TYPESPEC_CHAR:
869 g_string_append(str, "char");
870 break;
871 case TYPESPEC_SHORT:
872 g_string_append(str, "short");
873 break;
874 case TYPESPEC_INT:
875 g_string_append(str, "int");
876 break;
877 case TYPESPEC_LONG:
878 g_string_append(str, "long");
879 break;
880 case TYPESPEC_FLOAT:
881 g_string_append(str, "float");
882 break;
883 case TYPESPEC_DOUBLE:
884 g_string_append(str, "double");
885 break;
886 case TYPESPEC_SIGNED:
887 g_string_append(str, "signed");
888 break;
889 case TYPESPEC_UNSIGNED:
890 g_string_append(str, "unsigned");
891 break;
892 case TYPESPEC_BOOL:
893 g_string_append(str, "bool");
894 break;
895 case TYPESPEC_COMPLEX:
896 g_string_append(str, "_Complex");
897 break;
898 case TYPESPEC_IMAGINARY:
899 g_string_append(str, "_Imaginary");
900 break;
901 case TYPESPEC_CONST:
902 g_string_append(str, "const");
903 break;
904 case TYPESPEC_ID_TYPE:
905 if (cls_specifier->u.field_class_specifier.id_type) {
906 g_string_append(str, cls_specifier->u.field_class_specifier.id_type);
907 }
908 break;
909 case TYPESPEC_STRUCT:
910 {
911 struct ctf_node *node = cls_specifier->u.field_class_specifier.node;
912
913 if (!node->u._struct.name) {
914 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Unexpected empty structure field class name.");
915 ret = -EINVAL;
916 goto end;
917 }
918
919 g_string_append(str, "struct ");
920 g_string_append(str, node->u._struct.name);
921 break;
922 }
923 case TYPESPEC_VARIANT:
924 {
925 struct ctf_node *node = cls_specifier->u.field_class_specifier.node;
926
927 if (!node->u.variant.name) {
928 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Unexpected empty variant field class name.");
929 ret = -EINVAL;
930 goto end;
931 }
932
933 g_string_append(str, "variant ");
934 g_string_append(str, node->u.variant.name);
935 break;
936 }
937 case TYPESPEC_ENUM:
938 {
939 struct ctf_node *node = cls_specifier->u.field_class_specifier.node;
940
941 if (!node->u._enum.enum_id) {
942 _BT_CPPLOGE_APPEND_CAUSE_NODE(
943 node, "Unexpected empty enumeration field class (`enum`) name.");
944 ret = -EINVAL;
945 goto end;
946 }
947
948 g_string_append(str, "enum ");
949 g_string_append(str, node->u._enum.enum_id);
950 break;
951 }
952 case TYPESPEC_FLOATING_POINT:
953 case TYPESPEC_INTEGER:
954 case TYPESPEC_STRING:
955 default:
956 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier->u.field_class_specifier.node,
957 "Unexpected field class specifier type: {}",
958 cls_specifier->u.field_class_specifier.type);
959 ret = -EINVAL;
960 goto end;
961 }
962
963 end:
964 return ret;
965 }
966
967 static int get_class_specifier_list_name(struct ctf_visitor_generate_ir *ctx,
968 struct ctf_node *cls_specifier_list, GString *str)
969 {
970 int ret = 0;
971 struct ctf_node *iter;
972 int alias_item_nr = 0;
973 struct bt_list_head *head = &cls_specifier_list->u.field_class_specifier_list.head;
974
975 bt_list_for_each_entry (iter, head, siblings) {
976 if (alias_item_nr != 0) {
977 g_string_append(str, " ");
978 }
979
980 alias_item_nr++;
981 ret = get_class_specifier_name(ctx, iter, str);
982 if (ret) {
983 goto end;
984 }
985 }
986
987 end:
988 return ret;
989 }
990
991 static GQuark create_class_alias_identifier(struct ctf_visitor_generate_ir *ctx,
992 struct ctf_node *cls_specifier_list,
993 struct ctf_node *node_field_class_declarator)
994 {
995 int ret;
996 char *str_c;
997 GString *str;
998 GQuark qalias = 0;
999 struct ctf_node *iter;
1000 struct bt_list_head *pointers = &node_field_class_declarator->u.field_class_declarator.pointers;
1001
1002 str = g_string_new("");
1003 ret = get_class_specifier_list_name(ctx, cls_specifier_list, str);
1004 if (ret) {
1005 g_string_free(str, TRUE);
1006 goto end;
1007 }
1008
1009 bt_list_for_each_entry (iter, pointers, siblings) {
1010 g_string_append(str, " *");
1011
1012 if (iter->u.pointer.const_qualifier) {
1013 g_string_append(str, " const");
1014 }
1015 }
1016
1017 str_c = g_string_free(str, FALSE);
1018 qalias = g_quark_from_string(str_c);
1019 g_free(str_c);
1020
1021 end:
1022 return qalias;
1023 }
1024
1025 static int visit_field_class_declarator(struct ctf_visitor_generate_ir *ctx,
1026 struct ctf_node *cls_specifier_list, GQuark *field_name,
1027 struct ctf_node *node_field_class_declarator,
1028 struct ctf_field_class **field_decl,
1029 struct ctf_field_class *nested_decl)
1030 {
1031 /*
1032 * During this whole function, nested_decl is always OURS,
1033 * whereas field_decl is an output which we create, but
1034 * belongs to the caller (it is moved).
1035 */
1036 int ret = 0;
1037 *field_decl = NULL;
1038
1039 /* Validate field class declarator node */
1040 if (node_field_class_declarator) {
1041 if (node_field_class_declarator->u.field_class_declarator.type == TYPEDEC_UNKNOWN) {
1042 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1043 node_field_class_declarator, "Unexpected field class declarator type: type={}",
1044 node_field_class_declarator->u.field_class_declarator.type);
1045 ret = -EINVAL;
1046 goto error;
1047 }
1048
1049 /* TODO: GCC bitfields not supported yet */
1050 if (node_field_class_declarator->u.field_class_declarator.bitfield_len != NULL) {
1051 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1052 "GCC bitfields are not supported as of this version.");
1053 ret = -EPERM;
1054 goto error;
1055 }
1056 }
1057
1058 /* Find the right nested declaration if not provided */
1059 if (!nested_decl) {
1060 if (node_field_class_declarator &&
1061 !bt_list_empty(&node_field_class_declarator->u.field_class_declarator.pointers)) {
1062 GQuark qalias;
1063
1064 /*
1065 * If we have a pointer declarator, it HAS to
1066 * be present in the field class aliases (else
1067 * fail).
1068 */
1069 qalias =
1070 create_class_alias_identifier(ctx, cls_specifier_list, node_field_class_declarator);
1071 nested_decl = ctx_decl_scope_lookup_alias(ctx->current_scope, g_quark_to_string(qalias),
1072 -1, true);
1073 if (!nested_decl) {
1074 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1075 "Cannot find class alias: name=\"{}\"",
1076 g_quark_to_string(qalias));
1077 ret = -EINVAL;
1078 goto error;
1079 }
1080
1081 if (nested_decl->type == CTF_FIELD_CLASS_TYPE_INT) {
1082 /* Pointer: force integer's base to 16 */
1083 struct ctf_field_class_int *int_fc = ctf_field_class_as_int(nested_decl);
1084
1085 int_fc->disp_base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
1086 }
1087 } else {
1088 ret = visit_field_class_specifier_list(ctx, cls_specifier_list, &nested_decl);
1089 if (ret) {
1090 BT_ASSERT(!nested_decl);
1091 goto error;
1092 }
1093 }
1094 }
1095
1096 BT_ASSERT(nested_decl);
1097
1098 if (!node_field_class_declarator) {
1099 *field_decl = nested_decl;
1100 nested_decl = NULL;
1101 goto end;
1102 }
1103
1104 if (node_field_class_declarator->u.field_class_declarator.type == TYPEDEC_ID) {
1105 if (node_field_class_declarator->u.field_class_declarator.u.id) {
1106 const char *id = node_field_class_declarator->u.field_class_declarator.u.id;
1107
1108 *field_name = g_quark_from_string(id);
1109 } else {
1110 *field_name = 0;
1111 }
1112
1113 *field_decl = nested_decl;
1114 nested_decl = NULL;
1115 goto end;
1116 } else {
1117 struct ctf_node *first;
1118 struct ctf_field_class *decl = NULL;
1119 struct ctf_field_class *outer_field_decl = NULL;
1120 struct bt_list_head *length =
1121 &node_field_class_declarator->u.field_class_declarator.u.nested.length;
1122
1123 /* Create array/sequence, pass nested_decl as child */
1124 if (bt_list_empty(length)) {
1125 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1126 "Expecting length field reference or value.");
1127 ret = -EINVAL;
1128 goto error;
1129 }
1130
1131 first = _BT_LIST_FIRST_ENTRY(length, struct ctf_node, siblings);
1132 if (first->type != NODE_UNARY_EXPRESSION) {
1133 _BT_CPPLOGE_APPEND_CAUSE_NODE(first, "Unexpected node type: node-type={}", first->type);
1134 ret = -EINVAL;
1135 goto error;
1136 }
1137
1138 switch (first->u.unary_expression.type) {
1139 case UNARY_UNSIGNED_CONSTANT:
1140 {
1141 struct ctf_field_class_array *array_decl = NULL;
1142
1143 array_decl = ctf_field_class_array_create();
1144 BT_ASSERT(array_decl);
1145 array_decl->length = first->u.unary_expression.u.unsigned_constant;
1146 array_decl->base.elem_fc = nested_decl;
1147 nested_decl = NULL;
1148 decl = &array_decl->base.base;
1149 break;
1150 }
1151 case UNARY_STRING:
1152 {
1153 /* Lookup unsigned integer definition, create seq. */
1154 struct ctf_field_class_sequence *seq_decl = NULL;
1155 char *length_name = ctf_ast_concatenate_unary_strings(length);
1156
1157 if (!length_name) {
1158 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1159 "Cannot concatenate unary strings.");
1160 ret = -EINVAL;
1161 goto error;
1162 }
1163
1164 if (strncmp(length_name, "env.", 4) == 0) {
1165 /* This is, in fact, an array */
1166 const char *env_entry_name = &length_name[4];
1167 struct ctf_trace_class_env_entry *env_entry =
1168 ctf_trace_class_borrow_env_entry_by_name(ctx->ctf_tc, env_entry_name);
1169 struct ctf_field_class_array *array_decl;
1170
1171 if (!env_entry) {
1172 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1173 "Cannot find environment entry: "
1174 "name=\"{}\"",
1175 env_entry_name);
1176 ret = -EINVAL;
1177 goto error;
1178 }
1179
1180 if (env_entry->type != CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT) {
1181 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1182 "Wrong environment entry type "
1183 "(expecting integer): "
1184 "name=\"{}\"",
1185 env_entry_name);
1186 ret = -EINVAL;
1187 goto error;
1188 }
1189
1190 if (env_entry->value.i < 0) {
1191 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1192 "Invalid, negative array length: "
1193 "env-entry-name=\"{}\", "
1194 "value={}",
1195 env_entry_name, env_entry->value.i);
1196 ret = -EINVAL;
1197 goto error;
1198 }
1199
1200 array_decl = ctf_field_class_array_create();
1201 BT_ASSERT(array_decl);
1202 array_decl->length = (uint64_t) env_entry->value.i;
1203 array_decl->base.elem_fc = nested_decl;
1204 nested_decl = NULL;
1205 decl = &array_decl->base.base;
1206 } else {
1207 seq_decl = ctf_field_class_sequence_create();
1208 BT_ASSERT(seq_decl);
1209 seq_decl->base.elem_fc = nested_decl;
1210 nested_decl = NULL;
1211 g_string_assign(seq_decl->length_ref, length_name);
1212 decl = &seq_decl->base.base;
1213 }
1214
1215 g_free(length_name);
1216 break;
1217 }
1218 default:
1219 ret = -EINVAL;
1220 goto error;
1221 }
1222
1223 BT_ASSERT(!nested_decl);
1224 BT_ASSERT(decl);
1225 BT_ASSERT(!*field_decl);
1226
1227 /*
1228 * At this point, we found the next nested declaration.
1229 * We currently own this (and lost the ownership of
1230 * nested_decl in the meantime). Pass this next
1231 * nested declaration as the content of the outer
1232 * container, MOVING its ownership.
1233 */
1234 ret = visit_field_class_declarator(
1235 ctx, cls_specifier_list, field_name,
1236 node_field_class_declarator->u.field_class_declarator.u.nested.field_class_declarator,
1237 &outer_field_decl, decl);
1238 decl = NULL;
1239 if (ret) {
1240 BT_ASSERT(!outer_field_decl);
1241 ret = -EINVAL;
1242 goto error;
1243 }
1244
1245 BT_ASSERT(outer_field_decl);
1246 *field_decl = outer_field_decl;
1247 outer_field_decl = NULL;
1248 }
1249
1250 BT_ASSERT(*field_decl);
1251 goto end;
1252
1253 error:
1254 ctf_field_class_destroy(*field_decl);
1255 *field_decl = NULL;
1256
1257 if (ret >= 0) {
1258 ret = -1;
1259 }
1260
1261 end:
1262 ctf_field_class_destroy(nested_decl);
1263 nested_decl = NULL;
1264 return ret;
1265 }
1266
1267 static int visit_struct_decl_field(struct ctf_visitor_generate_ir *ctx,
1268 struct ctf_field_class_struct *struct_decl,
1269 struct ctf_node *cls_specifier_list,
1270 struct bt_list_head *field_class_declarators)
1271 {
1272 int ret = 0;
1273 struct ctf_node *iter;
1274 struct ctf_field_class *field_decl = NULL;
1275
1276 bt_list_for_each_entry (iter, field_class_declarators, siblings) {
1277 field_decl = NULL;
1278 GQuark qfield_name;
1279 const char *field_name;
1280
1281 ret = visit_field_class_declarator(ctx, cls_specifier_list, &qfield_name, iter, &field_decl,
1282 NULL);
1283 if (ret) {
1284 BT_ASSERT(!field_decl);
1285 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list,
1286 "Cannot visit field class declarator: ret={}", ret);
1287 goto error;
1288 }
1289
1290 BT_ASSERT(field_decl);
1291 field_name = g_quark_to_string(qfield_name);
1292
1293 /* Check if field with same name already exists */
1294 if (ctf_field_class_struct_borrow_member_by_name(struct_decl, field_name)) {
1295 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list,
1296 "Duplicate field in structure field class: "
1297 "field-name=\"{}\"",
1298 field_name);
1299 ret = -EINVAL;
1300 goto error;
1301 }
1302
1303 /* Add field to structure */
1304 ctf_field_class_struct_append_member(struct_decl, field_name, field_decl);
1305 field_decl = NULL;
1306 }
1307
1308 return 0;
1309
1310 error:
1311 ctf_field_class_destroy(field_decl);
1312 field_decl = NULL;
1313 return ret;
1314 }
1315
1316 static int visit_variant_decl_field(struct ctf_visitor_generate_ir *ctx,
1317 struct ctf_field_class_variant *variant_decl,
1318 struct ctf_node *cls_specifier_list,
1319 struct bt_list_head *field_class_declarators)
1320 {
1321 int ret = 0;
1322 struct ctf_node *iter;
1323 struct ctf_field_class *field_decl = NULL;
1324
1325 bt_list_for_each_entry (iter, field_class_declarators, siblings) {
1326 field_decl = NULL;
1327 GQuark qfield_name;
1328 const char *field_name;
1329
1330 ret = visit_field_class_declarator(ctx, cls_specifier_list, &qfield_name, iter, &field_decl,
1331 NULL);
1332 if (ret) {
1333 BT_ASSERT(!field_decl);
1334 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list,
1335 "Cannot visit field class declarator: ret={}", ret);
1336 goto error;
1337 }
1338
1339 BT_ASSERT(field_decl);
1340 field_name = g_quark_to_string(qfield_name);
1341
1342 /* Check if field with same name already exists */
1343 if (ctf_field_class_variant_borrow_option_by_name(variant_decl, field_name)) {
1344 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list,
1345 "Duplicate field in variant field class: "
1346 "field-name=\"{}\"",
1347 field_name);
1348 ret = -EINVAL;
1349 goto error;
1350 }
1351
1352 /* Add field to structure */
1353 ctf_field_class_variant_append_option(variant_decl, field_name, field_decl);
1354 field_decl = NULL;
1355 }
1356
1357 return 0;
1358
1359 error:
1360 ctf_field_class_destroy(field_decl);
1361 field_decl = NULL;
1362 return ret;
1363 }
1364
1365 static int visit_field_class_def(struct ctf_visitor_generate_ir *ctx,
1366 struct ctf_node *cls_specifier_list,
1367 struct bt_list_head *field_class_declarators)
1368 {
1369 int ret = 0;
1370 GQuark qidentifier;
1371 struct ctf_node *iter;
1372 struct ctf_field_class *class_decl = NULL;
1373
1374 bt_list_for_each_entry (iter, field_class_declarators, siblings) {
1375 ret = visit_field_class_declarator(ctx, cls_specifier_list, &qidentifier, iter, &class_decl,
1376 NULL);
1377 if (ret) {
1378 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter, "Cannot visit field class declarator: ret={}", ret);
1379 ret = -EINVAL;
1380 goto end;
1381 }
1382
1383 /* Do not allow field class def and alias of untagged variants */
1384 if (class_decl->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
1385 struct ctf_field_class_variant *var_fc = ctf_field_class_as_variant(class_decl);
1386
1387 if (var_fc->tag_path.path->len == 0) {
1388 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1389 iter, "Type definition of untagged variant field class is not allowed.");
1390 ret = -EPERM;
1391 goto end;
1392 }
1393 }
1394
1395 ret = ctx_decl_scope_register_alias(ctx->current_scope, g_quark_to_string(qidentifier),
1396 class_decl);
1397 if (ret) {
1398 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter, "Cannot register field class alias: name=\"{}\"",
1399 g_quark_to_string(qidentifier));
1400 goto end;
1401 }
1402 }
1403
1404 end:
1405 ctf_field_class_destroy(class_decl);
1406 class_decl = NULL;
1407 return ret;
1408 }
1409
1410 static int visit_field_class_alias(struct ctf_visitor_generate_ir *ctx, struct ctf_node *target,
1411 struct ctf_node *alias)
1412 {
1413 int ret = 0;
1414 GQuark qalias;
1415 struct ctf_node *node;
1416 GQuark qdummy_field_name;
1417 struct ctf_field_class *class_decl = NULL;
1418
1419 /* Create target field class */
1420 if (bt_list_empty(&target->u.field_class_alias_target.field_class_declarators)) {
1421 node = NULL;
1422 } else {
1423 node = _BT_LIST_FIRST_ENTRY(&target->u.field_class_alias_target.field_class_declarators,
1424 struct ctf_node, siblings);
1425 }
1426
1427 ret = visit_field_class_declarator(
1428 ctx, target->u.field_class_alias_target.field_class_specifier_list, &qdummy_field_name,
1429 node, &class_decl, NULL);
1430 if (ret) {
1431 BT_ASSERT(!class_decl);
1432 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Cannot visit field class declarator: ret={}", ret);
1433 goto end;
1434 }
1435
1436 /* Do not allow field class def and alias of untagged variants */
1437 if (class_decl->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
1438 struct ctf_field_class_variant *var_fc = ctf_field_class_as_variant(class_decl);
1439
1440 if (var_fc->tag_path.path->len == 0) {
1441 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1442 target, "Type definition of untagged variant field class is not allowed.");
1443 ret = -EPERM;
1444 goto end;
1445 }
1446 }
1447
1448 /*
1449 * The semantic validator does not check whether the target is
1450 * abstract or not (if it has an identifier). Check it here.
1451 */
1452 if (qdummy_field_name != 0) {
1453 _BT_CPPLOGE_APPEND_CAUSE_NODE(target, "Expecting empty identifier: id=\"{}\"",
1454 g_quark_to_string(qdummy_field_name));
1455 ret = -EINVAL;
1456 goto end;
1457 }
1458
1459 /* Create alias identifier */
1460 node = _BT_LIST_FIRST_ENTRY(&alias->u.field_class_alias_name.field_class_declarators,
1461 struct ctf_node, siblings);
1462 qalias = create_class_alias_identifier(
1463 ctx, alias->u.field_class_alias_name.field_class_specifier_list, node);
1464 ret = ctx_decl_scope_register_alias(ctx->current_scope, g_quark_to_string(qalias), class_decl);
1465 if (ret) {
1466 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Cannot register class alias: name=\"{}\"",
1467 g_quark_to_string(qalias));
1468 goto end;
1469 }
1470
1471 end:
1472 ctf_field_class_destroy(class_decl);
1473 class_decl = NULL;
1474 return ret;
1475 }
1476
1477 static int visit_struct_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *entry_node,
1478 struct ctf_field_class_struct *struct_decl)
1479 {
1480 int ret = 0;
1481
1482 switch (entry_node->type) {
1483 case NODE_TYPEDEF:
1484 ret = visit_field_class_def(ctx, entry_node->u.field_class_def.field_class_specifier_list,
1485 &entry_node->u.field_class_def.field_class_declarators);
1486 if (ret) {
1487 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1488 entry_node, "Cannot add field class found in structure field class: ret={}", ret);
1489 goto end;
1490 }
1491 break;
1492 case NODE_TYPEALIAS:
1493 ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target,
1494 entry_node->u.field_class_alias.alias);
1495 if (ret) {
1496 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1497 entry_node, "Cannot add field class alias found in structure field class: ret={}",
1498 ret);
1499 goto end;
1500 }
1501 break;
1502 case NODE_STRUCT_OR_VARIANT_DECLARATION:
1503 /* Field */
1504 ret = visit_struct_decl_field(
1505 ctx, struct_decl,
1506 entry_node->u.struct_or_variant_declaration.field_class_specifier_list,
1507 &entry_node->u.struct_or_variant_declaration.field_class_declarators);
1508 if (ret) {
1509 goto end;
1510 }
1511 break;
1512 default:
1513 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node, "Unexpected node type: node-type={}",
1514 entry_node->type);
1515 ret = -EINVAL;
1516 goto end;
1517 }
1518
1519 end:
1520 return ret;
1521 }
1522
1523 static int visit_variant_decl_entry(struct ctf_visitor_generate_ir *ctx,
1524 struct ctf_node *entry_node,
1525 struct ctf_field_class_variant *variant_decl)
1526 {
1527 int ret = 0;
1528
1529 switch (entry_node->type) {
1530 case NODE_TYPEDEF:
1531 ret = visit_field_class_def(ctx, entry_node->u.field_class_def.field_class_specifier_list,
1532 &entry_node->u.field_class_def.field_class_declarators);
1533 if (ret) {
1534 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1535 entry_node, "Cannot add field class found in variant field class: ret={}", ret);
1536 goto end;
1537 }
1538 break;
1539 case NODE_TYPEALIAS:
1540 ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target,
1541 entry_node->u.field_class_alias.alias);
1542 if (ret) {
1543 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1544 entry_node, "Cannot add field class alias found in variant field class: ret={}",
1545 ret);
1546 goto end;
1547 }
1548 break;
1549 case NODE_STRUCT_OR_VARIANT_DECLARATION:
1550 /* Field */
1551 ret = visit_variant_decl_field(
1552 ctx, variant_decl,
1553 entry_node->u.struct_or_variant_declaration.field_class_specifier_list,
1554 &entry_node->u.struct_or_variant_declaration.field_class_declarators);
1555 if (ret) {
1556 goto end;
1557 }
1558 break;
1559 default:
1560 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node, "Unexpected node type: node-type={}",
1561 entry_node->type);
1562 ret = -EINVAL;
1563 goto end;
1564 }
1565
1566 end:
1567 return ret;
1568 }
1569
1570 static int visit_struct_decl(struct ctf_visitor_generate_ir *ctx, const char *name,
1571 struct bt_list_head *decl_list, int has_body,
1572 struct bt_list_head *min_align,
1573 struct ctf_field_class_struct **struct_decl)
1574 {
1575 int ret = 0;
1576
1577 BT_ASSERT(struct_decl);
1578 *struct_decl = NULL;
1579
1580 /* For named struct (without body), lookup in declaration scope */
1581 if (!has_body) {
1582 if (!name) {
1583 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger,
1584 "Bodyless structure field class: missing name.");
1585 ret = -EPERM;
1586 goto error;
1587 }
1588
1589 *struct_decl = ctx_decl_scope_lookup_struct(ctx->current_scope, name, -1, true);
1590 if (!*struct_decl) {
1591 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1592 ctx->logger, "Cannot find structure field class: name=\"struct {}\"", name);
1593 ret = -EINVAL;
1594 goto error;
1595 }
1596 } else {
1597 struct ctf_node *entry_node;
1598 uint64_t min_align_value = 0;
1599
1600 if (name) {
1601 if (ctx_decl_scope_lookup_struct(ctx->current_scope, name, 1, false)) {
1602 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1603 ctx->logger,
1604 "Structure field class already declared in local scope: "
1605 "name=\"struct {}\"",
1606 name);
1607 ret = -EINVAL;
1608 goto error;
1609 }
1610 }
1611
1612 if (!bt_list_empty(min_align)) {
1613 ret = get_unary_unsigned(ctx, min_align, &min_align_value);
1614 if (ret) {
1615 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1616 ctx->logger,
1617 "Unexpected unary expression for structure field class's `align` attribute: "
1618 "ret={}",
1619 ret);
1620 goto error;
1621 }
1622 }
1623
1624 *struct_decl = ctf_field_class_struct_create();
1625 BT_ASSERT(*struct_decl);
1626
1627 if (min_align_value != 0) {
1628 (*struct_decl)->base.alignment = min_align_value;
1629 }
1630
1631 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1632
1633 bt_list_for_each_entry (entry_node, decl_list, siblings) {
1634 ret = visit_struct_decl_entry(ctx, entry_node, *struct_decl);
1635 if (ret) {
1636 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node,
1637 "Cannot visit structure field class entry: "
1638 "ret={}",
1639 ret);
1640 ctx_pop_scope(ctx);
1641 goto error;
1642 }
1643 }
1644
1645 ctx_pop_scope(ctx);
1646
1647 if (name) {
1648 ret = ctx_decl_scope_register_struct(ctx->current_scope, name, *struct_decl);
1649 if (ret) {
1650 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1651 ctx->logger,
1652 "Cannot register structure field class in declaration scope: "
1653 "name=\"struct {}\", ret={}",
1654 name, ret);
1655 goto error;
1656 }
1657 }
1658 }
1659
1660 return 0;
1661
1662 error:
1663 ctf_field_class_destroy(&(*struct_decl)->base);
1664 *struct_decl = NULL;
1665 return ret;
1666 }
1667
1668 static int visit_variant_decl(struct ctf_visitor_generate_ir *ctx, const char *name,
1669 const char *tag, struct bt_list_head *decl_list, int has_body,
1670 struct ctf_field_class_variant **variant_decl)
1671 {
1672 int ret = 0;
1673 struct ctf_field_class_variant *untagged_variant_decl = NULL;
1674
1675 BT_ASSERT(variant_decl);
1676 *variant_decl = NULL;
1677
1678 /* For named variant (without body), lookup in declaration scope */
1679 if (!has_body) {
1680 if (!name) {
1681 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger,
1682 "Bodyless variant field class: missing name.");
1683 ret = -EPERM;
1684 goto error;
1685 }
1686
1687 untagged_variant_decl = ctx_decl_scope_lookup_variant(ctx->current_scope, name, -1, true);
1688 if (!untagged_variant_decl) {
1689 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1690 ctx->logger, "Cannot find variant field class: name=\"variant {}\"", name);
1691 ret = -EINVAL;
1692 goto error;
1693 }
1694 } else {
1695 struct ctf_node *entry_node;
1696
1697 if (name) {
1698 if (ctx_decl_scope_lookup_variant(ctx->current_scope, name, 1, false)) {
1699 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger,
1700 "Variant field class already declared in local scope: "
1701 "name=\"variant {}\"",
1702 name);
1703 ret = -EINVAL;
1704 goto error;
1705 }
1706 }
1707
1708 untagged_variant_decl = ctf_field_class_variant_create();
1709 BT_ASSERT(untagged_variant_decl);
1710 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1711
1712 bt_list_for_each_entry (entry_node, decl_list, siblings) {
1713 ret = visit_variant_decl_entry(ctx, entry_node, untagged_variant_decl);
1714 if (ret) {
1715 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node,
1716 "Cannot visit variant field class entry: "
1717 "ret={}",
1718 ret);
1719 ctx_pop_scope(ctx);
1720 goto error;
1721 }
1722 }
1723
1724 ctx_pop_scope(ctx);
1725
1726 if (name) {
1727 ret = ctx_decl_scope_register_variant(ctx->current_scope, name, untagged_variant_decl);
1728 if (ret) {
1729 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1730 ctx->logger,
1731 "Cannot register variant field class in declaration scope: "
1732 "name=\"variant {}\", ret={}",
1733 name, ret);
1734 goto error;
1735 }
1736 }
1737 }
1738
1739 /*
1740 * If tagged, create tagged variant and return; otherwise
1741 * return untagged variant.
1742 */
1743 if (!tag) {
1744 *variant_decl = untagged_variant_decl;
1745 untagged_variant_decl = NULL;
1746 } else {
1747 /*
1748 * At this point, we have a fresh untagged variant; nobody
1749 * else owns it. Set its tag now.
1750 */
1751 g_string_assign(untagged_variant_decl->tag_ref, tag);
1752 *variant_decl = untagged_variant_decl;
1753 untagged_variant_decl = NULL;
1754 }
1755
1756 BT_ASSERT(!untagged_variant_decl);
1757 BT_ASSERT(*variant_decl);
1758 return 0;
1759
1760 error:
1761 ctf_field_class_destroy(&untagged_variant_decl->base);
1762 untagged_variant_decl = NULL;
1763 ctf_field_class_destroy(&(*variant_decl)->base);
1764 *variant_decl = NULL;
1765 return ret;
1766 }
1767
1768 struct uori
1769 {
1770 bool is_signed;
1771 union
1772 {
1773 uint64_t u;
1774 uint64_t i;
1775 } value;
1776 };
1777
1778 static int visit_enum_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *enumerator,
1779 struct ctf_field_class_enum *enum_decl, struct uori *last)
1780 {
1781 int ret = 0;
1782 int nr_vals = 0;
1783 struct ctf_node *iter;
1784 struct uori start = {
1785 .is_signed = false,
1786 .value =
1787 {
1788 .u = 0,
1789 },
1790 };
1791 struct uori end = {
1792 .is_signed = false,
1793 .value =
1794 {
1795 .u = 0,
1796 },
1797 };
1798 const char *label = enumerator->u.enumerator.id;
1799 struct bt_list_head *values = &enumerator->u.enumerator.values;
1800
1801 bt_list_for_each_entry (iter, values, siblings) {
1802 struct uori *target;
1803
1804 if (iter->type != NODE_UNARY_EXPRESSION) {
1805 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter,
1806 "Wrong expression for enumeration field class label: "
1807 "node-type={}, label=\"{}\"",
1808 iter->type, label);
1809 ret = -EINVAL;
1810 goto error;
1811 }
1812
1813 if (nr_vals == 0) {
1814 target = &start;
1815 } else {
1816 target = &end;
1817 }
1818
1819 switch (iter->u.unary_expression.type) {
1820 case UNARY_SIGNED_CONSTANT:
1821 target->is_signed = true;
1822 target->value.i = iter->u.unary_expression.u.signed_constant;
1823 break;
1824 case UNARY_UNSIGNED_CONSTANT:
1825 target->is_signed = false;
1826 target->value.u = iter->u.unary_expression.u.unsigned_constant;
1827 break;
1828 default:
1829 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter,
1830 "Invalid enumeration field class entry: "
1831 "expecting constant signed or unsigned integer: "
1832 "node-type={}, label=\"{}\"",
1833 iter->u.unary_expression.type, label);
1834 ret = -EINVAL;
1835 goto error;
1836 }
1837
1838 if (nr_vals > 1) {
1839 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1840 iter, "Invalid enumeration field class entry: label=\"{}\"", label);
1841 ret = -EINVAL;
1842 goto error;
1843 }
1844
1845 nr_vals++;
1846 }
1847
1848 if (nr_vals == 0) {
1849 start = *last;
1850 }
1851
1852 if (nr_vals <= 1) {
1853 end = start;
1854 }
1855
1856 if (end.is_signed) {
1857 last->value.i = end.value.i + 1;
1858 } else {
1859 last->value.u = end.value.u + 1;
1860 }
1861
1862 ctf_field_class_enum_map_range(enum_decl, label, start.value.u, end.value.u);
1863 return 0;
1864
1865 error:
1866 return ret;
1867 }
1868
1869 static int visit_enum_decl(struct ctf_visitor_generate_ir *ctx, const char *name,
1870 struct ctf_node *container_cls, struct bt_list_head *enumerator_list,
1871 int has_body, struct ctf_field_class_enum **enum_decl)
1872 {
1873 int ret = 0;
1874 GQuark qdummy_id;
1875 struct ctf_field_class_int *integer_decl = NULL;
1876
1877 BT_ASSERT(enum_decl);
1878 *enum_decl = NULL;
1879
1880 /* For named enum (without body), lookup in declaration scope */
1881 if (!has_body) {
1882 if (!name) {
1883 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger,
1884 "Bodyless enumeration field class: missing name.");
1885 ret = -EPERM;
1886 goto error;
1887 }
1888
1889 *enum_decl = ctx_decl_scope_lookup_enum(ctx->current_scope, name, -1, true);
1890 if (!*enum_decl) {
1891 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger,
1892 "Cannot find enumeration field class: "
1893 "name=\"enum {}\"",
1894 name);
1895 ret = -EINVAL;
1896 goto error;
1897 }
1898 } else {
1899 struct ctf_node *iter;
1900 struct uori last_value = {
1901 .is_signed = false,
1902 .value =
1903 {
1904 .u = 0,
1905 },
1906 };
1907
1908 if (name) {
1909 if (ctx_decl_scope_lookup_enum(ctx->current_scope, name, 1, false)) {
1910 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1911 ctx->logger,
1912 "Enumeration field class already declared in local scope: "
1913 "name=\"enum {}\"",
1914 name);
1915 ret = -EINVAL;
1916 goto error;
1917 }
1918 }
1919
1920 if (!container_cls) {
1921 integer_decl = ctf_field_class_as_int(
1922 ctx_decl_scope_lookup_alias(ctx->current_scope, "int", -1, true));
1923 if (!integer_decl) {
1924 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1925 ctx->logger,
1926 "Cannot find implicit `int` field class alias for enumeration field class.");
1927 ret = -EINVAL;
1928 goto error;
1929 }
1930 } else {
1931 ctf_field_class *decl;
1932
1933 ret = visit_field_class_declarator(ctx, container_cls, &qdummy_id, NULL, &decl, NULL);
1934 if (ret) {
1935 BT_ASSERT(!decl);
1936 ret = -EINVAL;
1937 goto error;
1938 }
1939
1940 integer_decl = ctf_field_class_as_int(decl);
1941 }
1942
1943 BT_ASSERT(integer_decl);
1944
1945 if (integer_decl->base.base.type != CTF_FIELD_CLASS_TYPE_INT) {
1946 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1947 ctx->logger,
1948 "Container field class for enumeration field class is not an integer field class: "
1949 "fc-type={}",
1950 integer_decl->base.base.type);
1951 ret = -EINVAL;
1952 goto error;
1953 }
1954
1955 *enum_decl = ctf_field_class_enum_create();
1956 BT_ASSERT(*enum_decl);
1957 (*enum_decl)->base.base.base.alignment = integer_decl->base.base.alignment;
1958 ctf_field_class_int_copy_content(&(*enum_decl)->base, integer_decl);
1959 last_value.is_signed = (*enum_decl)->base.is_signed;
1960
1961 bt_list_for_each_entry (iter, enumerator_list, siblings) {
1962 ret = visit_enum_decl_entry(ctx, iter, *enum_decl, &last_value);
1963 if (ret) {
1964 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter,
1965 "Cannot visit enumeration field class entry: "
1966 "ret={}",
1967 ret);
1968 goto error;
1969 }
1970 }
1971
1972 if (name) {
1973 ret = ctx_decl_scope_register_enum(ctx->current_scope, name, *enum_decl);
1974 if (ret) {
1975 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1976 ctx->logger,
1977 "Cannot register enumeration field class in declaration scope: "
1978 "ret={}",
1979 ret);
1980 goto error;
1981 }
1982 }
1983 }
1984
1985 goto end;
1986
1987 error:
1988 ctf_field_class_destroy(&(*enum_decl)->base.base.base);
1989 *enum_decl = NULL;
1990
1991 end:
1992 ctf_field_class_destroy(&integer_decl->base.base);
1993 integer_decl = NULL;
1994 return ret;
1995 }
1996
1997 static int visit_field_class_specifier(struct ctf_visitor_generate_ir *ctx,
1998 struct ctf_node *cls_specifier_list,
1999 struct ctf_field_class **decl)
2000 {
2001 int ret = 0;
2002 GString *str = NULL;
2003
2004 *decl = NULL;
2005 str = g_string_new("");
2006 ret = get_class_specifier_list_name(ctx, cls_specifier_list, str);
2007 if (ret) {
2008 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list,
2009 "Cannot get field class specifier list's name: ret={}", ret);
2010 goto error;
2011 }
2012
2013 *decl = ctx_decl_scope_lookup_alias(ctx->current_scope, str->str, -1, true);
2014 if (!*decl) {
2015 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list,
2016 "Cannot find field class alias: name=\"{}\"", str->str);
2017 ret = -EINVAL;
2018 goto error;
2019 }
2020
2021 goto end;
2022
2023 error:
2024 ctf_field_class_destroy(*decl);
2025 *decl = NULL;
2026
2027 end:
2028 if (str) {
2029 g_string_free(str, TRUE);
2030 }
2031
2032 return ret;
2033 }
2034
2035 static int visit_integer_decl(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *expressions,
2036 struct ctf_field_class_int **integer_decl)
2037 {
2038 int set = 0;
2039 int ret = 0;
2040 int signedness = 0;
2041 struct ctf_node *expression;
2042 uint64_t alignment = 0, size = 0;
2043 struct ctf_clock_class *mapped_clock_class = NULL;
2044 enum ctf_encoding encoding = CTF_ENCODING_NONE;
2045 bt_field_class_integer_preferred_display_base base =
2046 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
2047 enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
2048
2049 *integer_decl = NULL;
2050
2051 bt_list_for_each_entry (expression, expressions, siblings) {
2052 struct ctf_node *left, *right;
2053
2054 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left, struct ctf_node, siblings);
2055 right =
2056 _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.right, struct ctf_node, siblings);
2057
2058 if (left->u.unary_expression.type != UNARY_STRING) {
2059 _BT_CPPLOGE_APPEND_CAUSE_NODE(left, "Unexpected unary expression type: type={}",
2060 left->u.unary_expression.type);
2061 ret = -EINVAL;
2062 goto error;
2063 }
2064
2065 if (strcmp(left->u.unary_expression.u.string, "signed") == 0) {
2066 if (_IS_SET(&set, _INTEGER_SIGNED_SET)) {
2067 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left, "signed", "integer field class");
2068 ret = -EPERM;
2069 goto error;
2070 }
2071
2072 signedness = get_boolean(ctx, right);
2073 if (signedness < 0) {
2074 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2075 right,
2076 "Invalid boolean value for integer field class's `signed` attribute: "
2077 "ret={}",
2078 ret);
2079 ret = -EINVAL;
2080 goto error;
2081 }
2082
2083 _SET(&set, _INTEGER_SIGNED_SET);
2084 } else if (strcmp(left->u.unary_expression.u.string, "byte_order") == 0) {
2085 if (_IS_SET(&set, _INTEGER_BYTE_ORDER_SET)) {
2086 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left, "byte_order", "integer field class");
2087 ret = -EPERM;
2088 goto error;
2089 }
2090
2091 byte_order = get_real_byte_order(ctx, right);
2092 if (byte_order == CTF_BYTE_ORDER_UNKNOWN) {
2093 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2094 right,
2095 "Invalid `byte_order` attribute in integer field class: "
2096 "ret={}",
2097 ret);
2098 ret = -EINVAL;
2099 goto error;
2100 }
2101
2102 _SET(&set, _INTEGER_BYTE_ORDER_SET);
2103 } else if (strcmp(left->u.unary_expression.u.string, "size") == 0) {
2104 if (_IS_SET(&set, _INTEGER_SIZE_SET)) {
2105 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left, "size", "integer field class");
2106 ret = -EPERM;
2107 goto error;
2108 }
2109
2110 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
2111 _BT_CPPLOGE_APPEND_CAUSE_NODE(right,
2112 "Invalid `size` attribute in integer field class: "
2113 "expecting unsigned constant integer: "
2114 "node-type={}",
2115 right->u.unary_expression.type);
2116 ret = -EINVAL;
2117 goto error;
2118 }
2119
2120 size = right->u.unary_expression.u.unsigned_constant;
2121 if (size == 0) {
2122 _BT_CPPLOGE_APPEND_CAUSE_NODE(right,
2123 "Invalid `size` attribute in integer field class: "
2124 "expecting positive constant integer: "
2125 "size={}",
2126 size);
2127 ret = -EINVAL;
2128 goto error;
2129 } else if (size > 64) {
2130 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2131 right,
2132 "Invalid `size` attribute in integer field class: "
2133 "integer fields over 64 bits are not supported as of this version: "
2134 "size={}",
2135 size);
2136 ret = -EINVAL;
2137 goto error;
2138 }
2139
2140 _SET(&set, _INTEGER_SIZE_SET);
2141 } else if (strcmp(left->u.unary_expression.u.string, "align") == 0) {
2142 if (_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2143 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left, "align", "integer field class");
2144 ret = -EPERM;
2145 goto error;
2146 }
2147
2148 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
2149 _BT_CPPLOGE_APPEND_CAUSE_NODE(right,
2150 "Invalid `align` attribute in integer field class: "
2151 "expecting unsigned constant integer: "
2152 "node-type={}",
2153 right->u.unary_expression.type);
2154 ret = -EINVAL;
2155 goto error;
2156 }
2157
2158 alignment = right->u.unary_expression.u.unsigned_constant;
2159 if (!is_align_valid(alignment)) {
2160 _BT_CPPLOGE_APPEND_CAUSE_NODE(right,
2161 "Invalid `align` attribute in integer field class: "
2162 "expecting power of two: "
2163 "align={}",
2164 alignment);
2165 ret = -EINVAL;
2166 goto error;
2167 }
2168
2169 _SET(&set, _INTEGER_ALIGN_SET);
2170 } else if (strcmp(left->u.unary_expression.u.string, "base") == 0) {
2171 if (_IS_SET(&set, _INTEGER_BASE_SET)) {
2172 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left, "base", "integer field class");
2173 ret = -EPERM;
2174 goto error;
2175 }
2176
2177 switch (right->u.unary_expression.type) {
2178 case UNARY_UNSIGNED_CONSTANT:
2179 {
2180 uint64_t constant = right->u.unary_expression.u.unsigned_constant;
2181
2182 switch (constant) {
2183 case 2:
2184 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY;
2185 break;
2186 case 8:
2187 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL;
2188 break;
2189 case 10:
2190 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
2191 break;
2192 case 16:
2193 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
2194 break;
2195 default:
2196 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2197 right,
2198 "Invalid `base` attribute in integer field class: "
2199 "base={}",
2200 right->u.unary_expression.u.unsigned_constant);
2201 ret = -EINVAL;
2202 goto error;
2203 }
2204 break;
2205 }
2206 case UNARY_STRING:
2207 {
2208 char *s_right =
2209 ctf_ast_concatenate_unary_strings(&expression->u.ctf_expression.right);
2210 if (!s_right) {
2211 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2212 right,
2213 "Unexpected unary expression for integer field class's `base` attribute.");
2214 ret = -EINVAL;
2215 goto error;
2216 }
2217
2218 if (strcmp(s_right, "decimal") == 0 || strcmp(s_right, "dec") == 0 ||
2219 strcmp(s_right, "d") == 0 || strcmp(s_right, "i") == 0 ||
2220 strcmp(s_right, "u") == 0) {
2221 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
2222 } else if (strcmp(s_right, "hexadecimal") == 0 || strcmp(s_right, "hex") == 0 ||
2223 strcmp(s_right, "x") == 0 || strcmp(s_right, "X") == 0 ||
2224 strcmp(s_right, "p") == 0) {
2225 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
2226 } else if (strcmp(s_right, "octal") == 0 || strcmp(s_right, "oct") == 0 ||
2227 strcmp(s_right, "o") == 0) {
2228 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL;
2229 } else if (strcmp(s_right, "binary") == 0 || strcmp(s_right, "b") == 0) {
2230 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY;
2231 } else {
2232 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2233 right,
2234 "Unexpected unary expression for integer field class's `base` attribute: "
2235 "base=\"{}\"",
2236 s_right);
2237 g_free(s_right);
2238 ret = -EINVAL;
2239 goto error;
2240 }
2241
2242 g_free(s_right);
2243 break;
2244 }
2245 default:
2246 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2247 right, "Invalid `base` attribute in integer field class: "
2248 "expecting unsigned constant integer or unary string.");
2249 ret = -EINVAL;
2250 goto error;
2251 }
2252
2253 _SET(&set, _INTEGER_BASE_SET);
2254 } else if (strcmp(left->u.unary_expression.u.string, "encoding") == 0) {
2255 char *s_right;
2256
2257 if (_IS_SET(&set, _INTEGER_ENCODING_SET)) {
2258 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left, "encoding", "integer field class");
2259 ret = -EPERM;
2260 goto error;
2261 }
2262
2263 if (right->u.unary_expression.type != UNARY_STRING) {
2264 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2265 right, "Invalid `encoding` attribute in integer field class: "
2266 "expecting unary string.");
2267 ret = -EINVAL;
2268 goto error;
2269 }
2270
2271 s_right = ctf_ast_concatenate_unary_strings(&expression->u.ctf_expression.right);
2272 if (!s_right) {
2273 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2274 right,
2275 "Unexpected unary expression for integer field class's `encoding` attribute.");
2276 ret = -EINVAL;
2277 goto error;
2278 }
2279
2280 if (strcmp(s_right, "UTF8") == 0 || strcmp(s_right, "utf8") == 0 ||
2281 strcmp(s_right, "utf-8") == 0 || strcmp(s_right, "UTF-8") == 0 ||
2282 strcmp(s_right, "ASCII") == 0 || strcmp(s_right, "ascii") == 0) {
2283 encoding = CTF_ENCODING_UTF8;
2284 } else if (strcmp(s_right, "none") == 0) {
2285 encoding = CTF_ENCODING_NONE;
2286 } else {
2287 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2288 right,
2289 "Invalid `encoding` attribute in integer field class: "
2290 "unknown encoding: encoding=\"{}\"",
2291 s_right);
2292 g_free(s_right);
2293 ret = -EINVAL;
2294 goto error;
2295 }
2296
2297 g_free(s_right);
2298 _SET(&set, _INTEGER_ENCODING_SET);
2299 } else if (strcmp(left->u.unary_expression.u.string, "map") == 0) {
2300 const char *clock_name;
2301
2302 if (_IS_SET(&set, _INTEGER_MAP_SET)) {
2303 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left, "map", "integer field class");
2304 ret = -EPERM;
2305 goto error;
2306 }
2307
2308 if (right->u.unary_expression.type != UNARY_STRING) {
2309 _BT_CPPLOGE_APPEND_CAUSE_NODE(right,
2310 "Invalid `map` attribute in integer field class: "
2311 "expecting unary string.");
2312 ret = -EINVAL;
2313 goto error;
2314 }
2315
2316 clock_name = get_map_clock_name_value(&expression->u.ctf_expression.right);
2317 if (!clock_name) {
2318 char *s_right =
2319 ctf_ast_concatenate_unary_strings(&expression->u.ctf_expression.right);
2320
2321 if (!s_right) {
2322 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2323 right,
2324 "Unexpected unary expression for integer field class's `map` attribute.");
2325 ret = -EINVAL;
2326 goto error;
2327 }
2328
2329 _BT_CPPLOGE_NODE(right,
2330 "Invalid `map` attribute in integer field class: "
2331 "cannot find clock class at this point: name=\"{}\"",
2332 s_right);
2333 _SET(&set, _INTEGER_MAP_SET);
2334 g_free(s_right);
2335 continue;
2336 }
2337
2338 mapped_clock_class =
2339 ctf_trace_class_borrow_clock_class_by_name(ctx->ctf_tc, clock_name);
2340 if (!mapped_clock_class) {
2341 _BT_CPPLOGE_APPEND_CAUSE_NODE(right,
2342 "Invalid `map` attribute in integer field class: "
2343 "cannot find clock class at this point: name=\"{}\"",
2344 clock_name);
2345 ret = -EINVAL;
2346 goto error;
2347 }
2348
2349 _SET(&set, _INTEGER_MAP_SET);
2350 } else {
2351 _BT_CPPLOGW_NODE(left,
2352 "Unknown attribute in integer field class: "
2353 "attr-name=\"{}\"",
2354 left->u.unary_expression.u.string);
2355 }
2356 }
2357
2358 if (!_IS_SET(&set, _INTEGER_SIZE_SET)) {
2359 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger,
2360 "Missing `size` attribute in integer field class.");
2361 ret = -EPERM;
2362 goto error;
2363 }
2364
2365 if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2366 if (size % CHAR_BIT) {
2367 /* Bit-packed alignment */
2368 alignment = 1;
2369 } else {
2370 /* Byte-packed alignment */
2371 alignment = CHAR_BIT;
2372 }
2373 }
2374
2375 *integer_decl = ctf_field_class_int_create();
2376 BT_ASSERT(*integer_decl);
2377 (*integer_decl)->base.base.alignment = alignment;
2378 (*integer_decl)->base.byte_order = byte_order;
2379 (*integer_decl)->base.size = size;
2380 (*integer_decl)->is_signed = (signedness > 0);
2381 (*integer_decl)->disp_base = base;
2382 (*integer_decl)->encoding = encoding;
2383 (*integer_decl)->mapped_clock_class = mapped_clock_class;
2384 return 0;
2385
2386 error:
2387 ctf_field_class_destroy(&(*integer_decl)->base.base);
2388 *integer_decl = NULL;
2389 return ret;
2390 }
2391
2392 static int visit_floating_point_number_decl(struct ctf_visitor_generate_ir *ctx,
2393 struct bt_list_head *expressions,
2394 struct ctf_field_class_float **float_decl)
2395 {
2396 int set = 0;
2397 int ret = 0;
2398 struct ctf_node *expression;
2399 uint64_t alignment = 1, exp_dig = 0, mant_dig = 0;
2400 enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
2401
2402 *float_decl = NULL;
2403
2404 bt_list_for_each_entry (expression, expressions, siblings) {
2405 struct ctf_node *left, *right;
2406
2407 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left, struct ctf_node, siblings);
2408 right =
2409 _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.right, struct ctf_node, siblings);
2410
2411 if (left->u.unary_expression.type != UNARY_STRING) {
2412 _BT_CPPLOGE_APPEND_CAUSE_NODE(left, "Unexpected unary expression type: type={}",
2413 left->u.unary_expression.type);
2414 ret = -EINVAL;
2415 goto error;
2416 }
2417
2418 if (strcmp(left->u.unary_expression.u.string, "byte_order") == 0) {
2419 if (_IS_SET(&set, _FLOAT_BYTE_ORDER_SET)) {
2420 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left, "byte_order",
2421 "floating point number field class");
2422 ret = -EPERM;
2423 goto error;
2424 }
2425
2426 byte_order = get_real_byte_order(ctx, right);
2427 if (byte_order == CTF_BYTE_ORDER_UNKNOWN) {
2428 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2429 right,
2430 "Invalid `byte_order` attribute in floating point number field class: "
2431 "ret={}",
2432 ret);
2433 ret = -EINVAL;
2434 goto error;
2435 }
2436
2437 _SET(&set, _FLOAT_BYTE_ORDER_SET);
2438 } else if (strcmp(left->u.unary_expression.u.string, "exp_dig") == 0) {
2439 if (_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
2440 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left, "exp_dig",
2441 "floating point number field class");
2442 ret = -EPERM;
2443 goto error;
2444 }
2445
2446 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
2447 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2448 right,
2449 "Invalid `exp_dig` attribute in floating point number field class: "
2450 "expecting unsigned constant integer: "
2451 "node-type={}",
2452 right->u.unary_expression.type);
2453 ret = -EINVAL;
2454 goto error;
2455 }
2456
2457 exp_dig = right->u.unary_expression.u.unsigned_constant;
2458 _SET(&set, _FLOAT_EXP_DIG_SET);
2459 } else if (strcmp(left->u.unary_expression.u.string, "mant_dig") == 0) {
2460 if (_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
2461 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left, "mant_dig",
2462 "floating point number field class");
2463 ret = -EPERM;
2464 goto error;
2465 }
2466
2467 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
2468 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2469 right,
2470 "Invalid `mant_dig` attribute in floating point number field class: "
2471 "expecting unsigned constant integer: "
2472 "node-type={}",
2473 right->u.unary_expression.type);
2474 ret = -EINVAL;
2475 goto error;
2476 }
2477
2478 mant_dig = right->u.unary_expression.u.unsigned_constant;
2479 _SET(&set, _FLOAT_MANT_DIG_SET);
2480 } else if (strcmp(left->u.unary_expression.u.string, "align") == 0) {
2481 if (_IS_SET(&set, _FLOAT_ALIGN_SET)) {
2482 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left, "align",
2483 "floating point number field class");
2484 ret = -EPERM;
2485 goto error;
2486 }
2487
2488 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
2489 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2490 right,
2491 "Invalid `align` attribute in floating point number field class: "
2492 "expecting unsigned constant integer: "
2493 "node-type={}",
2494 right->u.unary_expression.type);
2495 ret = -EINVAL;
2496 goto error;
2497 }
2498
2499 alignment = right->u.unary_expression.u.unsigned_constant;
2500
2501 if (!is_align_valid(alignment)) {
2502 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2503 right,
2504 "Invalid `align` attribute in floating point number field class: "
2505 "expecting power of two: "
2506 "align={}",
2507 alignment);
2508 ret = -EINVAL;
2509 goto error;
2510 }
2511
2512 _SET(&set, _FLOAT_ALIGN_SET);
2513 } else {
2514 _BT_CPPLOGW_NODE(left,
2515 "Unknown attribute in floating point number field class: "
2516 "attr-name=\"{}\"",
2517 left->u.unary_expression.u.string);
2518 }
2519 }
2520
2521 if (!_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
2522 BT_CPPLOGE_APPEND_CAUSE_SPEC(
2523 ctx->logger, "Missing `mant_dig` attribute in floating point number field class.");
2524 ret = -EPERM;
2525 goto error;
2526 }
2527
2528 if (!_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
2529 BT_CPPLOGE_APPEND_CAUSE_SPEC(
2530 ctx->logger, "Missing `exp_dig` attribute in floating point number field class.");
2531 ret = -EPERM;
2532 goto error;
2533 }
2534
2535 if (mant_dig != 24 && mant_dig != 53) {
2536 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger, "`mant_dig` attribute: expecting 24 or 53.");
2537 ret = -EPERM;
2538 goto error;
2539 }
2540
2541 if (mant_dig == 24 && exp_dig != 8) {
2542 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger,
2543 "`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2544 ret = -EPERM;
2545 goto error;
2546 }
2547
2548 if (mant_dig == 53 && exp_dig != 11) {
2549 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger,
2550 "`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2551 ret = -EPERM;
2552 goto error;
2553 }
2554
2555 if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2556 if ((mant_dig + exp_dig) % CHAR_BIT) {
2557 /* Bit-packed alignment */
2558 alignment = 1;
2559 } else {
2560 /* Byte-packed alignment */
2561 alignment = CHAR_BIT;
2562 }
2563 }
2564
2565 *float_decl = ctf_field_class_float_create();
2566 BT_ASSERT(*float_decl);
2567 (*float_decl)->base.base.alignment = alignment;
2568 (*float_decl)->base.byte_order = byte_order;
2569 (*float_decl)->base.size = mant_dig + exp_dig;
2570 return 0;
2571
2572 error:
2573 ctf_field_class_destroy(&(*float_decl)->base.base);
2574 *float_decl = NULL;
2575 return ret;
2576 }
2577
2578 static int visit_string_decl(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *expressions,
2579 struct ctf_field_class_string **string_decl)
2580 {
2581 int set = 0;
2582 int ret = 0;
2583 struct ctf_node *expression;
2584 enum ctf_encoding encoding = CTF_ENCODING_UTF8;
2585
2586 *string_decl = NULL;
2587
2588 bt_list_for_each_entry (expression, expressions, siblings) {
2589 struct ctf_node *left, *right;
2590
2591 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left, struct ctf_node, siblings);
2592 right =
2593 _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.right, struct ctf_node, siblings);
2594
2595 if (left->u.unary_expression.type != UNARY_STRING) {
2596 _BT_CPPLOGE_APPEND_CAUSE_NODE(left, "Unexpected unary expression type: type={}",
2597 left->u.unary_expression.type);
2598 ret = -EINVAL;
2599 goto error;
2600 }
2601
2602 if (strcmp(left->u.unary_expression.u.string, "encoding") == 0) {
2603 char *s_right;
2604
2605 if (_IS_SET(&set, _STRING_ENCODING_SET)) {
2606 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left, "encoding", "string field class");
2607 ret = -EPERM;
2608 goto error;
2609 }
2610
2611 if (right->u.unary_expression.type != UNARY_STRING) {
2612 _BT_CPPLOGE_APPEND_CAUSE_NODE(right,
2613 "Invalid `encoding` attribute in string field class: "
2614 "expecting unary string.");
2615 ret = -EINVAL;
2616 goto error;
2617 }
2618
2619 s_right = ctf_ast_concatenate_unary_strings(&expression->u.ctf_expression.right);
2620 if (!s_right) {
2621 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2622 right,
2623 "Unexpected unary expression for string field class's `encoding` attribute.");
2624 ret = -EINVAL;
2625 goto error;
2626 }
2627
2628 if (strcmp(s_right, "UTF8") == 0 || strcmp(s_right, "utf8") == 0 ||
2629 strcmp(s_right, "utf-8") == 0 || strcmp(s_right, "UTF-8") == 0 ||
2630 strcmp(s_right, "ASCII") == 0 || strcmp(s_right, "ascii") == 0) {
2631 encoding = CTF_ENCODING_UTF8;
2632 } else if (strcmp(s_right, "none") == 0) {
2633 encoding = CTF_ENCODING_NONE;
2634 } else {
2635 _BT_CPPLOGE_APPEND_CAUSE_NODE(right,
2636 "Invalid `encoding` attribute in string field class: "
2637 "unknown encoding: encoding=\"{}\"",
2638 s_right);
2639 g_free(s_right);
2640 ret = -EINVAL;
2641 goto error;
2642 }
2643
2644 g_free(s_right);
2645 _SET(&set, _STRING_ENCODING_SET);
2646 } else {
2647 _BT_CPPLOGW_NODE(left,
2648 "Unknown attribute in string field class: "
2649 "attr-name=\"{}\"",
2650 left->u.unary_expression.u.string);
2651 }
2652 }
2653
2654 *string_decl = ctf_field_class_string_create();
2655 BT_ASSERT(*string_decl);
2656 (*string_decl)->encoding = encoding;
2657 return 0;
2658
2659 error:
2660 ctf_field_class_destroy(&(*string_decl)->base);
2661 *string_decl = NULL;
2662 return ret;
2663 }
2664
2665 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir *ctx,
2666 struct ctf_node *ts_list, struct ctf_field_class **decl)
2667 {
2668 int ret = 0;
2669 struct ctf_node *first, *node;
2670
2671 *decl = NULL;
2672
2673 if (ts_list->type != NODE_TYPE_SPECIFIER_LIST) {
2674 _BT_CPPLOGE_APPEND_CAUSE_NODE(ts_list, "Unexpected node type: node-type={}", ts_list->type);
2675 ret = -EINVAL;
2676 goto error;
2677 }
2678
2679 first = _BT_LIST_FIRST_ENTRY(&ts_list->u.field_class_specifier_list.head, struct ctf_node,
2680 siblings);
2681 if (first->type != NODE_TYPE_SPECIFIER) {
2682 _BT_CPPLOGE_APPEND_CAUSE_NODE(first, "Unexpected node type: node-type={}", first->type);
2683 ret = -EINVAL;
2684 goto error;
2685 }
2686
2687 node = first->u.field_class_specifier.node;
2688
2689 switch (first->u.field_class_specifier.type) {
2690 case TYPESPEC_INTEGER:
2691 {
2692 ctf_field_class_int *int_decl;
2693
2694 ret = visit_integer_decl(ctx, &node->u.integer.expressions, &int_decl);
2695 if (ret) {
2696 BT_ASSERT(!int_decl);
2697 goto error;
2698 }
2699
2700 *decl = &int_decl->base.base;
2701 break;
2702 }
2703 case TYPESPEC_FLOATING_POINT:
2704 {
2705 ctf_field_class_float *float_decl;
2706
2707 ret =
2708 visit_floating_point_number_decl(ctx, &node->u.floating_point.expressions, &float_decl);
2709 if (ret) {
2710 BT_ASSERT(!float_decl);
2711 goto error;
2712 }
2713
2714 *decl = &float_decl->base.base;
2715 break;
2716 }
2717 case TYPESPEC_STRING:
2718 {
2719 ctf_field_class_string *string_decl;
2720
2721 ret = visit_string_decl(ctx, &node->u.string.expressions, &string_decl);
2722 if (ret) {
2723 BT_ASSERT(!string_decl);
2724 goto error;
2725 }
2726
2727 *decl = &string_decl->base;
2728 break;
2729 }
2730 case TYPESPEC_STRUCT:
2731 {
2732 ctf_field_class_struct *struct_decl;
2733
2734 ret = visit_struct_decl(ctx, node->u._struct.name, &node->u._struct.declaration_list,
2735 node->u._struct.has_body, &node->u._struct.min_align, &struct_decl);
2736 if (ret) {
2737 BT_ASSERT(!struct_decl);
2738 goto error;
2739 }
2740
2741 *decl = &struct_decl->base;
2742 break;
2743 }
2744 case TYPESPEC_VARIANT:
2745 {
2746 ctf_field_class_variant *variant_decl;
2747
2748 ret = visit_variant_decl(ctx, node->u.variant.name, node->u.variant.choice,
2749 &node->u.variant.declaration_list, node->u.variant.has_body,
2750 &variant_decl);
2751 if (ret) {
2752 BT_ASSERT(!variant_decl);
2753 goto error;
2754 }
2755
2756 *decl = &variant_decl->base;
2757 break;
2758 }
2759 case TYPESPEC_ENUM:
2760 {
2761 ctf_field_class_enum *enum_decl;
2762
2763 ret = visit_enum_decl(ctx, node->u._enum.enum_id, node->u._enum.container_field_class,
2764 &node->u._enum.enumerator_list, node->u._enum.has_body, &enum_decl);
2765 if (ret) {
2766 BT_ASSERT(!enum_decl);
2767 goto error;
2768 }
2769
2770 *decl = &enum_decl->base.base.base;
2771 break;
2772 }
2773 case TYPESPEC_VOID:
2774 case TYPESPEC_CHAR:
2775 case TYPESPEC_SHORT:
2776 case TYPESPEC_INT:
2777 case TYPESPEC_LONG:
2778 case TYPESPEC_FLOAT:
2779 case TYPESPEC_DOUBLE:
2780 case TYPESPEC_SIGNED:
2781 case TYPESPEC_UNSIGNED:
2782 case TYPESPEC_BOOL:
2783 case TYPESPEC_COMPLEX:
2784 case TYPESPEC_IMAGINARY:
2785 case TYPESPEC_CONST:
2786 case TYPESPEC_ID_TYPE:
2787 ret = visit_field_class_specifier(ctx, ts_list, decl);
2788 if (ret) {
2789 _BT_CPPLOGE_APPEND_CAUSE_NODE(first, "Cannot visit field class specifier: ret={}", ret);
2790 BT_ASSERT(!*decl);
2791 goto error;
2792 }
2793 break;
2794 default:
2795 _BT_CPPLOGE_APPEND_CAUSE_NODE(first, "Unexpected field class specifier type: node-type={}",
2796 first->u.field_class_specifier.type);
2797 ret = -EINVAL;
2798 goto error;
2799 }
2800
2801 BT_ASSERT(*decl);
2802 return 0;
2803
2804 error:
2805 ctf_field_class_destroy(*decl);
2806 *decl = NULL;
2807 return ret;
2808 }
2809
2810 static int visit_event_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node,
2811 struct ctf_event_class *event_class, uint64_t *stream_id,
2812 int *set)
2813 {
2814 int ret = 0;
2815 char *left = NULL;
2816
2817 switch (node->type) {
2818 case NODE_TYPEDEF:
2819 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
2820 &node->u.field_class_def.field_class_declarators);
2821 if (ret) {
2822 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Cannot add field class found in event class.");
2823 goto error;
2824 }
2825 break;
2826 case NODE_TYPEALIAS:
2827 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
2828 node->u.field_class_alias.alias);
2829 if (ret) {
2830 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
2831 "Cannot add field class alias found in event class.");
2832 goto error;
2833 }
2834 break;
2835 case NODE_CTF_EXPRESSION:
2836 {
2837 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
2838 if (!left) {
2839 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
2840 ret = -EINVAL;
2841 goto error;
2842 }
2843
2844 if (strcmp(left, "name") == 0) {
2845 /* This is already known at this stage */
2846 if (_IS_SET(set, _EVENT_NAME_SET)) {
2847 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node, "name", "event class");
2848 ret = -EPERM;
2849 goto error;
2850 }
2851
2852 _SET(set, _EVENT_NAME_SET);
2853 } else if (strcmp(left, "id") == 0) {
2854 int64_t id = -1;
2855
2856 if (_IS_SET(set, _EVENT_ID_SET)) {
2857 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node, "id", "event class");
2858 ret = -EPERM;
2859 goto error;
2860 }
2861
2862 ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, (uint64_t *) &id);
2863 /* Only read "id" if get_unary_unsigned() succeeded. */
2864 if (ret || (!ret && id < 0)) {
2865 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2866 node, "Unexpected unary expression for event class's `id` attribute.");
2867 ret = -EINVAL;
2868 goto error;
2869 }
2870
2871 event_class->id = id;
2872 _SET(set, _EVENT_ID_SET);
2873 } else if (strcmp(left, "stream_id") == 0) {
2874 if (_IS_SET(set, _EVENT_STREAM_ID_SET)) {
2875 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node, "stream_id", "event class");
2876 ret = -EPERM;
2877 goto error;
2878 }
2879
2880 ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, stream_id);
2881
2882 /*
2883 * Only read "stream_id" if get_unary_unsigned()
2884 * succeeded.
2885 */
2886 if (ret) {
2887 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2888 node, "Unexpected unary expression for event class's `stream_id` attribute.");
2889 ret = -EINVAL;
2890 goto error;
2891 }
2892
2893 _SET(set, _EVENT_STREAM_ID_SET);
2894 } else if (strcmp(left, "context") == 0) {
2895 if (_IS_SET(set, _EVENT_CONTEXT_SET)) {
2896 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Duplicate `context` entry in event class.");
2897 ret = -EPERM;
2898 goto error;
2899 }
2900
2901 ret = visit_field_class_specifier_list(
2902 ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings),
2903 &event_class->spec_context_fc);
2904 if (ret) {
2905 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
2906 "Cannot create event class's context field class.");
2907 goto error;
2908 }
2909
2910 BT_ASSERT(event_class->spec_context_fc);
2911 _SET(set, _EVENT_CONTEXT_SET);
2912 } else if (strcmp(left, "fields") == 0) {
2913 if (_IS_SET(set, _EVENT_FIELDS_SET)) {
2914 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Duplicate `fields` entry in event class.");
2915 ret = -EPERM;
2916 goto error;
2917 }
2918
2919 ret = visit_field_class_specifier_list(
2920 ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings),
2921 &event_class->payload_fc);
2922 if (ret) {
2923 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
2924 "Cannot create event class's payload field class.");
2925 goto error;
2926 }
2927
2928 BT_ASSERT(event_class->payload_fc);
2929 _SET(set, _EVENT_FIELDS_SET);
2930 } else if (strcmp(left, "loglevel") == 0) {
2931 uint64_t loglevel_value;
2932 bool is_log_level_known = true;
2933 bt_event_class_log_level log_level;
2934
2935 if (_IS_SET(set, _EVENT_LOG_LEVEL_SET)) {
2936 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node, "loglevel", "event class");
2937 ret = -EPERM;
2938 goto error;
2939 }
2940
2941 ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, &loglevel_value);
2942 if (ret) {
2943 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2944 node, "Unexpected unary expression for event class's `loglevel` attribute.");
2945 ret = -EINVAL;
2946 goto error;
2947 }
2948
2949 switch (loglevel_value) {
2950 case 0:
2951 log_level = BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY;
2952 break;
2953 case 1:
2954 log_level = BT_EVENT_CLASS_LOG_LEVEL_ALERT;
2955 break;
2956 case 2:
2957 log_level = BT_EVENT_CLASS_LOG_LEVEL_CRITICAL;
2958 break;
2959 case 3:
2960 log_level = BT_EVENT_CLASS_LOG_LEVEL_ERROR;
2961 break;
2962 case 4:
2963 log_level = BT_EVENT_CLASS_LOG_LEVEL_WARNING;
2964 break;
2965 case 5:
2966 log_level = BT_EVENT_CLASS_LOG_LEVEL_NOTICE;
2967 break;
2968 case 6:
2969 log_level = BT_EVENT_CLASS_LOG_LEVEL_INFO;
2970 break;
2971 case 7:
2972 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM;
2973 break;
2974 case 8:
2975 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM;
2976 break;
2977 case 9:
2978 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS;
2979 break;
2980 case 10:
2981 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE;
2982 break;
2983 case 11:
2984 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT;
2985 break;
2986 case 12:
2987 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION;
2988 break;
2989 case 13:
2990 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE;
2991 break;
2992 case 14:
2993 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG;
2994 break;
2995 default:
2996 is_log_level_known = false;
2997 _BT_CPPLOGW_NODE(
2998 node,
2999 "Not setting event class's log level because its value is unknown: "
3000 "log-level={}",
3001 loglevel_value);
3002 }
3003
3004 if (is_log_level_known) {
3005 ctf_event_class_set_log_level(event_class, log_level);
3006 }
3007
3008 _SET(set, _EVENT_LOG_LEVEL_SET);
3009 } else if (strcmp(left, "model.emf.uri") == 0) {
3010 char *right;
3011
3012 if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) {
3013 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node, "model.emf.uri", "event class");
3014 ret = -EPERM;
3015 goto error;
3016 }
3017
3018 right = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.right);
3019 if (!right) {
3020 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3021 node,
3022 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3023 ret = -EINVAL;
3024 goto error;
3025 }
3026
3027 if (strlen(right) == 0) {
3028 _BT_CPPLOGW_NODE(node, "Not setting event class's EMF URI because it's empty.");
3029 } else {
3030 g_string_assign(event_class->emf_uri, right);
3031 }
3032
3033 g_free(right);
3034 _SET(set, _EVENT_MODEL_EMF_URI_SET);
3035 } else {
3036 _BT_CPPLOGW_NODE(node,
3037 "Unknown attribute in event class: "
3038 "attr-name=\"{}\"",
3039 left);
3040 }
3041
3042 g_free(left);
3043 left = NULL;
3044 break;
3045 }
3046 default:
3047 ret = -EPERM;
3048 goto error;
3049 }
3050
3051 goto end;
3052
3053 error:
3054 g_free(left);
3055
3056 end:
3057 return ret;
3058 }
3059
3060 static char *get_event_decl_name(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
3061 {
3062 char *left = NULL;
3063 char *name = NULL;
3064 struct ctf_node *iter;
3065 struct bt_list_head *decl_list = &node->u.event.declaration_list;
3066
3067 bt_list_for_each_entry (iter, decl_list, siblings) {
3068 if (iter->type != NODE_CTF_EXPRESSION) {
3069 continue;
3070 }
3071
3072 left = ctf_ast_concatenate_unary_strings(&iter->u.ctf_expression.left);
3073 if (!left) {
3074 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter, "Cannot concatenate unary strings.");
3075 goto error;
3076 }
3077
3078 if (strcmp(left, "name") == 0) {
3079 name = ctf_ast_concatenate_unary_strings(&iter->u.ctf_expression.right);
3080 if (!name) {
3081 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3082 iter, "Unexpected unary expression for event class's `name` attribute.");
3083 goto error;
3084 }
3085 }
3086
3087 g_free(left);
3088 left = NULL;
3089
3090 if (name) {
3091 break;
3092 }
3093 }
3094
3095 return name;
3096
3097 error:
3098 g_free(left);
3099 return NULL;
3100 }
3101
3102 static int visit_event_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
3103 {
3104 int ret = 0;
3105 int set = 0;
3106 struct ctf_node *iter;
3107 uint64_t stream_id = 0;
3108 char *event_name = NULL;
3109 struct ctf_event_class *event_class = NULL;
3110 struct ctf_stream_class *stream_class = NULL;
3111 struct bt_list_head *decl_list = &node->u.event.declaration_list;
3112 bool pop_scope = false;
3113
3114 if (node->visited) {
3115 goto end;
3116 }
3117
3118 node->visited = TRUE;
3119 event_name = get_event_decl_name(ctx, node);
3120 if (!event_name) {
3121 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Missing `name` attribute in event class.");
3122 ret = -EPERM;
3123 goto error;
3124 }
3125
3126 event_class = ctf_event_class_create();
3127 BT_ASSERT(event_class);
3128 g_string_assign(event_class->name, event_name);
3129 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3130 pop_scope = true;
3131
3132 bt_list_for_each_entry (iter, decl_list, siblings) {
3133 ret = visit_event_decl_entry(ctx, iter, event_class, &stream_id, &set);
3134 if (ret) {
3135 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter,
3136 "Cannot visit event class's entry: "
3137 "ret={}",
3138 ret);
3139 goto error;
3140 }
3141 }
3142
3143 if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) {
3144 /*
3145 * Allow missing stream_id if there is only a single
3146 * stream class.
3147 */
3148 switch (ctx->ctf_tc->stream_classes->len) {
3149 case 0:
3150 /* Create implicit stream class if there's none */
3151 stream_id = 0;
3152 stream_class = ctf_stream_class_create();
3153 BT_ASSERT(stream_class);
3154 stream_class->id = stream_id;
3155 g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class);
3156 break;
3157 case 1:
3158 /* Single stream class: get its ID */
3159 stream_class = (ctf_stream_class *) ctx->ctf_tc->stream_classes->pdata[0];
3160 stream_id = stream_class->id;
3161 break;
3162 default:
3163 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Missing `stream_id` attribute in event class.");
3164 ret = -EPERM;
3165 goto error;
3166 }
3167 }
3168
3169 /* We have the stream ID now; get the stream class if found */
3170 if (!stream_class) {
3171 stream_class = ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc, stream_id);
3172 if (!stream_class) {
3173 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
3174 "Cannot find stream class at this point: "
3175 "id={}",
3176 stream_id);
3177 ret = -EINVAL;
3178 goto error;
3179 }
3180 }
3181
3182 BT_ASSERT(stream_class);
3183
3184 if (!_IS_SET(&set, _EVENT_ID_SET)) {
3185 /* Allow only one event without ID per stream */
3186 if (stream_class->event_classes->len != 0) {
3187 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Missing `id` attribute in event class.");
3188 ret = -EPERM;
3189 goto error;
3190 }
3191
3192 /* Automatic ID */
3193 event_class->id = 0;
3194 }
3195
3196 if (ctf_stream_class_borrow_event_class_by_id(stream_class, event_class->id)) {
3197 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
3198 "Duplicate event class (same ID) in the same stream class: "
3199 "id={}",
3200 event_class->id);
3201 ret = -EEXIST;
3202 goto error;
3203 }
3204
3205 ctf_stream_class_append_event_class(stream_class, event_class);
3206 event_class = NULL;
3207 goto end;
3208
3209 error:
3210 ctf_event_class_destroy(event_class);
3211 event_class = NULL;
3212
3213 if (ret >= 0) {
3214 ret = -1;
3215 }
3216
3217 end:
3218 if (pop_scope) {
3219 ctx_pop_scope(ctx);
3220 }
3221
3222 g_free(event_name);
3223
3224 return ret;
3225 }
3226
3227 static int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir *ctx,
3228 struct ctf_field_class *fc)
3229 {
3230 struct ctf_clock_class *clock_class_to_map_to = NULL;
3231 uint64_t clock_class_count;
3232
3233 if (!fc) {
3234 return 0;
3235 }
3236
3237 if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
3238 return 0;
3239 }
3240
3241 ctf_field_class_int *int_fc = ctf_field_class_as_int(fc);
3242
3243 if (int_fc->mapped_clock_class) {
3244 /* Already mapped */
3245 return 0;
3246 }
3247
3248 clock_class_count = ctx->ctf_tc->clock_classes->len;
3249
3250 switch (clock_class_count) {
3251 case 0:
3252 /*
3253 * No clock class exists in the trace at this point. Create an
3254 * implicit one at 1 GHz, named `default`, and use this clock
3255 * class.
3256 */
3257 clock_class_to_map_to = ctf_clock_class_create();
3258 BT_ASSERT(clock_class_to_map_to);
3259 clock_class_to_map_to->frequency = UINT64_C(1000000000);
3260 g_string_assign(clock_class_to_map_to->name, "default");
3261 g_ptr_array_add(ctx->ctf_tc->clock_classes, clock_class_to_map_to);
3262 break;
3263 case 1:
3264 /*
3265 * Only one clock class exists in the trace at this point: use
3266 * this one.
3267 */
3268 clock_class_to_map_to = (ctf_clock_class *) ctx->ctf_tc->clock_classes->pdata[0];
3269 break;
3270 default:
3271 /*
3272 * Timestamp field not mapped to a clock class and there's more
3273 * than one clock class in the trace: this is an error.
3274 */
3275 BT_CPPLOGE_APPEND_CAUSE_SPEC(
3276 ctx->logger, "Timestamp field found with no mapped clock class, "
3277 "but there's more than one clock class in the trace at this point.");
3278 return -1;
3279 }
3280
3281 BT_ASSERT(clock_class_to_map_to);
3282 int_fc->mapped_clock_class = clock_class_to_map_to;
3283
3284 return 0;
3285 }
3286
3287 static int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir *ctx,
3288 struct ctf_field_class *root_fc,
3289 const char *field_name)
3290 {
3291 int ret = 0;
3292 uint64_t i, count;
3293 struct ctf_field_class_struct *struct_fc = (ctf_field_class_struct *) root_fc;
3294 struct ctf_field_class_variant *var_fc = (ctf_field_class_variant *) root_fc;
3295
3296 if (!root_fc) {
3297 goto end;
3298 }
3299
3300 if (root_fc->type != CTF_FIELD_CLASS_TYPE_STRUCT &&
3301 root_fc->type != CTF_FIELD_CLASS_TYPE_VARIANT) {
3302 goto end;
3303 }
3304
3305 if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
3306 count = struct_fc->members->len;
3307 } else {
3308 count = var_fc->options->len;
3309 }
3310
3311 for (i = 0; i < count; i++) {
3312 struct ctf_named_field_class *named_fc = NULL;
3313
3314 if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
3315 named_fc = ctf_field_class_struct_borrow_member_by_index(struct_fc, i);
3316 } else if (root_fc->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
3317 named_fc = ctf_field_class_variant_borrow_option_by_index(var_fc, i);
3318 } else {
3319 bt_common_abort();
3320 }
3321
3322 if (strcmp(named_fc->name->str, field_name) == 0) {
3323 ret = auto_map_field_to_trace_clock_class(ctx, named_fc->fc);
3324 if (ret) {
3325 BT_CPPLOGE_APPEND_CAUSE_SPEC(
3326 ctx->logger,
3327 "Cannot automatically map field to trace's clock class: "
3328 "field-name=\"{}\"",
3329 field_name);
3330 goto end;
3331 }
3332 }
3333
3334 ret = auto_map_fields_to_trace_clock_class(ctx, named_fc->fc, field_name);
3335 if (ret) {
3336 BT_CPPLOGE_APPEND_CAUSE_SPEC(
3337 ctx->logger,
3338 "Cannot automatically map structure or variant field class's fields to trace's clock class: "
3339 "field-name=\"{}\", root-field-name=\"{}\"",
3340 field_name, named_fc->name->str);
3341 goto end;
3342 }
3343 }
3344
3345 end:
3346 return ret;
3347 }
3348
3349 static int visit_stream_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node,
3350 struct ctf_stream_class *stream_class, int *set)
3351 {
3352 int ret = 0;
3353 char *left = NULL;
3354
3355 switch (node->type) {
3356 case NODE_TYPEDEF:
3357 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3358 &node->u.field_class_def.field_class_declarators);
3359 if (ret) {
3360 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Cannot add field class found in stream class.");
3361 goto error;
3362 }
3363 break;
3364 case NODE_TYPEALIAS:
3365 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3366 node->u.field_class_alias.alias);
3367 if (ret) {
3368 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
3369 "Cannot add field class alias found in stream class.");
3370 goto error;
3371 }
3372 break;
3373 case NODE_CTF_EXPRESSION:
3374 {
3375 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
3376 if (!left) {
3377 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
3378 ret = -EINVAL;
3379 goto error;
3380 }
3381
3382 if (strcmp(left, "id") == 0) {
3383 int64_t id;
3384
3385 if (_IS_SET(set, _STREAM_ID_SET)) {
3386 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node, "id", "stream declaration");
3387 ret = -EPERM;
3388 goto error;
3389 }
3390
3391 ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, (uint64_t *) &id);
3392
3393 /* Only read "id" if get_unary_unsigned() succeeded. */
3394 if (ret || (!ret && id < 0)) {
3395 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3396 node, "Unexpected unary expression for stream class's `id` attribute.");
3397 ret = -EINVAL;
3398 goto error;
3399 }
3400
3401 if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc, id)) {
3402 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Duplicate stream class (same ID): id={}", id);
3403 ret = -EEXIST;
3404 goto error;
3405 }
3406
3407 stream_class->id = id;
3408 _SET(set, _STREAM_ID_SET);
3409 } else if (strcmp(left, "event.header") == 0) {
3410 if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) {
3411 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
3412 "Duplicate `event.header` entry in stream class.");
3413 ret = -EPERM;
3414 goto error;
3415 }
3416
3417 ret = visit_field_class_specifier_list(
3418 ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings),
3419 &stream_class->event_header_fc);
3420 if (ret) {
3421 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3422 node, "Cannot create stream class's event header field class.");
3423 goto error;
3424 }
3425
3426 BT_ASSERT(stream_class->event_header_fc);
3427 ret = auto_map_fields_to_trace_clock_class(ctx, stream_class->event_header_fc,
3428 "timestamp");
3429 if (ret) {
3430 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3431 node,
3432 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3433 goto error;
3434 }
3435
3436 _SET(set, _STREAM_EVENT_HEADER_SET);
3437 } else if (strcmp(left, "event.context") == 0) {
3438 if (_IS_SET(set, _STREAM_EVENT_CONTEXT_SET)) {
3439 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
3440 "Duplicate `event.context` entry in stream class.");
3441 ret = -EPERM;
3442 goto error;
3443 }
3444
3445 ret = visit_field_class_specifier_list(
3446 ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings),
3447 &stream_class->event_common_context_fc);
3448 if (ret) {
3449 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3450 node, "Cannot create stream class's event context field class.");
3451 goto error;
3452 }
3453
3454 BT_ASSERT(stream_class->event_common_context_fc);
3455 _SET(set, _STREAM_EVENT_CONTEXT_SET);
3456 } else if (strcmp(left, "packet.context") == 0) {
3457 if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) {
3458 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
3459 "Duplicate `packet.context` entry in stream class.");
3460 ret = -EPERM;
3461 goto error;
3462 }
3463
3464 ret = visit_field_class_specifier_list(
3465 ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings),
3466 &stream_class->packet_context_fc);
3467 if (ret) {
3468 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3469 node, "Cannot create stream class's packet context field class.");
3470 goto error;
3471 }
3472
3473 BT_ASSERT(stream_class->packet_context_fc);
3474 ret = auto_map_fields_to_trace_clock_class(ctx, stream_class->packet_context_fc,
3475 "timestamp_begin");
3476 if (ret) {
3477 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3478 node,
3479 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3480 goto error;
3481 }
3482
3483 ret = auto_map_fields_to_trace_clock_class(ctx, stream_class->packet_context_fc,
3484 "timestamp_end");
3485 if (ret) {
3486 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3487 node,
3488 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3489 goto error;
3490 }
3491
3492 _SET(set, _STREAM_PACKET_CONTEXT_SET);
3493 } else {
3494 _BT_CPPLOGW_NODE(node,
3495 "Unknown attribute in stream class: "
3496 "attr-name=\"{}\"",
3497 left);
3498 }
3499
3500 g_free(left);
3501 left = NULL;
3502 break;
3503 }
3504
3505 default:
3506 ret = -EPERM;
3507 goto error;
3508 }
3509
3510 return 0;
3511
3512 error:
3513 g_free(left);
3514 return ret;
3515 }
3516
3517 static int visit_stream_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
3518 {
3519 int set = 0;
3520 int ret = 0;
3521 struct ctf_node *iter;
3522 struct ctf_stream_class *stream_class = NULL;
3523 struct bt_list_head *decl_list = &node->u.stream.declaration_list;
3524
3525 if (node->visited) {
3526 goto end;
3527 }
3528
3529 node->visited = TRUE;
3530 stream_class = ctf_stream_class_create();
3531 BT_ASSERT(stream_class);
3532 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3533
3534 bt_list_for_each_entry (iter, decl_list, siblings) {
3535 ret = visit_stream_decl_entry(ctx, iter, stream_class, &set);
3536 if (ret) {
3537 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter,
3538 "Cannot visit stream class's entry: "
3539 "ret={}",
3540 ret);
3541 ctx_pop_scope(ctx);
3542 goto error;
3543 }
3544 }
3545
3546 ctx_pop_scope(ctx);
3547
3548 if (_IS_SET(&set, _STREAM_ID_SET)) {
3549 /* Check that packet header has `stream_id` field */
3550 struct ctf_named_field_class *named_fc = NULL;
3551
3552 if (!ctx->ctf_tc->packet_header_fc) {
3553 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Stream class has a `id` attribute, "
3554 "but trace has no packet header field class.");
3555 ret = -EINVAL;
3556 goto error;
3557 }
3558
3559 named_fc = ctf_field_class_struct_borrow_member_by_name(
3560 ctf_field_class_as_struct(ctx->ctf_tc->packet_header_fc), "stream_id");
3561 if (!named_fc) {
3562 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3563 node, "Stream class has a `id` attribute, "
3564 "but trace's packet header field class has no `stream_id` field.");
3565 ret = -EINVAL;
3566 goto error;
3567 }
3568
3569 if (named_fc->fc->type != CTF_FIELD_CLASS_TYPE_INT &&
3570 named_fc->fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
3571 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3572 node,
3573 "Stream class has a `id` attribute, "
3574 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3575 ret = -EINVAL;
3576 goto error;
3577 }
3578 } else {
3579 /* Allow only _one_ ID-less stream */
3580 if (ctx->ctf_tc->stream_classes->len != 0) {
3581 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3582 node,
3583 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3584 ret = -EPERM;
3585 goto error;
3586 }
3587
3588 /* Automatic ID: 0 */
3589 stream_class->id = 0;
3590 }
3591
3592 /*
3593 * Make sure that this stream class's ID is currently unique in
3594 * the trace.
3595 */
3596 if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc, stream_class->id)) {
3597 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Duplicate stream class (same ID): id={}",
3598 stream_class->id);
3599 ret = -EINVAL;
3600 goto error;
3601 }
3602
3603 g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class);
3604 stream_class = NULL;
3605 goto end;
3606
3607 error:
3608 ctf_stream_class_destroy(stream_class);
3609 stream_class = NULL;
3610
3611 end:
3612 return ret;
3613 }
3614
3615 static int visit_trace_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node,
3616 int *set)
3617 {
3618 int ret = 0;
3619 char *left = NULL;
3620 uint64_t val;
3621
3622 switch (node->type) {
3623 case NODE_TYPEDEF:
3624 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3625 &node->u.field_class_def.field_class_declarators);
3626 if (ret) {
3627 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
3628 "Cannot add field class found in trace (`trace` block).");
3629 goto error;
3630 }
3631 break;
3632 case NODE_TYPEALIAS:
3633 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3634 node->u.field_class_alias.alias);
3635 if (ret) {
3636 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3637 node, "Cannot add field class alias found in trace (`trace` block).");
3638 goto error;
3639 }
3640 break;
3641 case NODE_CTF_EXPRESSION:
3642 {
3643 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
3644 if (!left) {
3645 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
3646 ret = -EINVAL;
3647 goto error;
3648 }
3649
3650 if (strcmp(left, "major") == 0) {
3651 if (_IS_SET(set, _TRACE_MAJOR_SET)) {
3652 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node, "major", "trace");
3653 ret = -EPERM;
3654 goto error;
3655 }
3656
3657 ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, &val);
3658 if (ret) {
3659 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3660 node, "Unexpected unary expression for trace's `major` attribute.");
3661 ret = -EINVAL;
3662 goto error;
3663 }
3664
3665 if (val != 1) {
3666 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
3667 "Invalid trace's `minor` attribute: expecting 1.");
3668 ret = -EINVAL;
3669 goto error;
3670 }
3671
3672 ctx->ctf_tc->major = val;
3673 _SET(set, _TRACE_MAJOR_SET);
3674 } else if (strcmp(left, "minor") == 0) {
3675 if (_IS_SET(set, _TRACE_MINOR_SET)) {
3676 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node, "minor", "trace");
3677 ret = -EPERM;
3678 goto error;
3679 }
3680
3681 ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, &val);
3682 if (ret) {
3683 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3684 node, "Unexpected unary expression for trace's `minor` attribute.");
3685 ret = -EINVAL;
3686 goto error;
3687 }
3688
3689 if (val != 8) {
3690 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
3691 "Invalid trace's `minor` attribute: expecting 8.");
3692 ret = -EINVAL;
3693 goto error;
3694 }
3695
3696 ctx->ctf_tc->minor = val;
3697 _SET(set, _TRACE_MINOR_SET);
3698 } else if (strcmp(left, "uuid") == 0) {
3699 if (_IS_SET(set, _TRACE_UUID_SET)) {
3700 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node, "uuid", "trace");
3701 ret = -EPERM;
3702 goto error;
3703 }
3704
3705 ret = get_unary_uuid(ctx, &node->u.ctf_expression.right, ctx->ctf_tc->uuid);
3706 if (ret) {
3707 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Invalid trace's `uuid` attribute.");
3708 goto error;
3709 }
3710
3711 ctx->ctf_tc->is_uuid_set = true;
3712 _SET(set, _TRACE_UUID_SET);
3713 } else if (strcmp(left, "byte_order") == 0) {
3714 /* Default byte order is already known at this stage */
3715 if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) {
3716 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node, "byte_order", "trace");
3717 ret = -EPERM;
3718 goto error;
3719 }
3720
3721 BT_ASSERT(ctx->ctf_tc->default_byte_order != CTF_BYTE_ORDER_UNKNOWN);
3722 _SET(set, _TRACE_BYTE_ORDER_SET);
3723 } else if (strcmp(left, "packet.header") == 0) {
3724 if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) {
3725 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Duplicate `packet.header` entry in trace.");
3726 ret = -EPERM;
3727 goto error;
3728 }
3729
3730 ret = visit_field_class_specifier_list(
3731 ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings),
3732 &ctx->ctf_tc->packet_header_fc);
3733 if (ret) {
3734 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
3735 "Cannot create trace's packet header field class.");
3736 goto error;
3737 }
3738
3739 BT_ASSERT(ctx->ctf_tc->packet_header_fc);
3740 _SET(set, _TRACE_PACKET_HEADER_SET);
3741 } else {
3742 _BT_CPPLOGW_NODE(node,
3743 "Unknown attribute in stream class: "
3744 "attr-name=\"{}\"",
3745 left);
3746 }
3747
3748 g_free(left);
3749 left = NULL;
3750 break;
3751 }
3752 default:
3753 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Unknown expression in trace.");
3754 ret = -EINVAL;
3755 goto error;
3756 }
3757
3758 return 0;
3759
3760 error:
3761 g_free(left);
3762 return ret;
3763 }
3764
3765 static int visit_trace_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
3766 {
3767 int ret = 0;
3768 int set = 0;
3769 struct ctf_node *iter;
3770 struct bt_list_head *decl_list = &node->u.trace.declaration_list;
3771
3772 if (node->visited) {
3773 goto end;
3774 }
3775
3776 node->visited = TRUE;
3777
3778 if (ctx->is_trace_visited) {
3779 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Duplicate trace (`trace` block).");
3780 ret = -EEXIST;
3781 goto error;
3782 }
3783
3784 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3785
3786 bt_list_for_each_entry (iter, decl_list, siblings) {
3787 ret = visit_trace_decl_entry(ctx, iter, &set);
3788 if (ret) {
3789 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter,
3790 "Cannot visit trace's entry (`trace` block): "
3791 "ret={}",
3792 ret);
3793 ctx_pop_scope(ctx);
3794 goto error;
3795 }
3796 }
3797
3798 ctx_pop_scope(ctx);
3799
3800 if (!_IS_SET(&set, _TRACE_MAJOR_SET)) {
3801 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Missing `major` attribute in trace (`trace` block).");
3802 ret = -EPERM;
3803 goto error;
3804 }
3805
3806 if (!_IS_SET(&set, _TRACE_MINOR_SET)) {
3807 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Missing `minor` attribute in trace (`trace` block).");
3808 ret = -EPERM;
3809 goto error;
3810 }
3811
3812 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
3813 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
3814 "Missing `byte_order` attribute in trace (`trace` block).");
3815 ret = -EPERM;
3816 goto error;
3817 }
3818
3819 ctx->is_trace_visited = true;
3820
3821 end:
3822 return 0;
3823
3824 error:
3825 return ret;
3826 }
3827
3828 static int visit_env(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
3829 {
3830 int ret = 0;
3831 char *left = NULL;
3832 struct ctf_node *entry_node;
3833 struct bt_list_head *decl_list = &node->u.env.declaration_list;
3834
3835 if (node->visited) {
3836 goto end;
3837 }
3838
3839 node->visited = TRUE;
3840
3841 bt_list_for_each_entry (entry_node, decl_list, siblings) {
3842 struct bt_list_head *right_head = &entry_node->u.ctf_expression.right;
3843
3844 if (entry_node->type != NODE_CTF_EXPRESSION) {
3845 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node,
3846 "Wrong expression in environment entry: "
3847 "node-type={}",
3848 entry_node->type);
3849 ret = -EPERM;
3850 goto error;
3851 }
3852
3853 left = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.left);
3854 if (!left) {
3855 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node, "Cannot get environment entry's name.");
3856 ret = -EINVAL;
3857 goto error;
3858 }
3859
3860 if (is_unary_string(right_head)) {
3861 char *right = ctf_ast_concatenate_unary_strings(right_head);
3862
3863 if (!right) {
3864 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3865 entry_node,
3866 "Unexpected unary expression for environment entry's value: "
3867 "name=\"{}\"",
3868 left);
3869 ret = -EINVAL;
3870 goto error;
3871 }
3872
3873 if (strcmp(left, "tracer_name") == 0) {
3874 if (strncmp(right, "lttng", 5) == 0) {
3875 BT_CPPLOGI_SPEC(ctx->logger,
3876 "Detected LTTng trace from `{}` environment value: "
3877 "tracer-name=\"{}\"",
3878 left, right);
3879 ctx->is_lttng = true;
3880 }
3881 }
3882
3883 ctf_trace_class_append_env_entry(ctx->ctf_tc, left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR,
3884 right, 0);
3885 g_free(right);
3886 } else if (is_unary_unsigned(right_head) || is_unary_signed(right_head)) {
3887 int64_t v;
3888
3889 if (is_unary_unsigned(right_head)) {
3890 ret = get_unary_unsigned(ctx, right_head, (uint64_t *) &v);
3891 } else {
3892 ret = get_unary_signed(right_head, &v);
3893 }
3894 if (ret) {
3895 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3896 entry_node,
3897 "Unexpected unary expression for environment entry's value: "
3898 "name=\"{}\"",
3899 left);
3900 ret = -EINVAL;
3901 goto error;
3902 }
3903
3904 ctf_trace_class_append_env_entry(ctx->ctf_tc, left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT,
3905 NULL, v);
3906 } else {
3907 _BT_CPPLOGW_NODE(entry_node,
3908 "Environment entry has unknown type: "
3909 "name=\"{}\"",
3910 left);
3911 }
3912
3913 g_free(left);
3914 left = NULL;
3915 }
3916
3917 end:
3918 return 0;
3919
3920 error:
3921 g_free(left);
3922 return ret;
3923 }
3924
3925 static int set_trace_byte_order(struct ctf_visitor_generate_ir *ctx, struct ctf_node *trace_node)
3926 {
3927 int ret = 0;
3928 int set = 0;
3929 char *left = NULL;
3930 struct ctf_node *node;
3931 struct bt_list_head *decl_list = &trace_node->u.trace.declaration_list;
3932
3933 bt_list_for_each_entry (node, decl_list, siblings) {
3934 if (node->type == NODE_CTF_EXPRESSION) {
3935 struct ctf_node *right_node;
3936
3937 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
3938 if (!left) {
3939 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
3940 ret = -EINVAL;
3941 goto error;
3942 }
3943
3944 if (strcmp(left, "byte_order") == 0) {
3945 enum ctf_byte_order bo;
3946
3947 if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
3948 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node, "byte_order", "trace");
3949 ret = -EPERM;
3950 goto error;
3951 }
3952
3953 _SET(&set, _TRACE_BYTE_ORDER_SET);
3954 right_node =
3955 _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings);
3956 bo = byte_order_from_unary_expr(ctx, right_node);
3957 if (bo == CTF_BYTE_ORDER_UNKNOWN) {
3958 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3959 node, "Invalid `byte_order` attribute in trace (`trace` block): "
3960 "expecting `le`, `be`, or `network`.");
3961 ret = -EINVAL;
3962 goto error;
3963 } else if (bo == CTF_BYTE_ORDER_DEFAULT) {
3964 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3965 node, "Invalid `byte_order` attribute in trace (`trace` block): "
3966 "cannot be set to `native` here.");
3967 ret = -EPERM;
3968 goto error;
3969 }
3970
3971 ctx->ctf_tc->default_byte_order = bo;
3972 }
3973
3974 g_free(left);
3975 left = NULL;
3976 }
3977 }
3978
3979 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
3980 _BT_CPPLOGE_APPEND_CAUSE_NODE(trace_node,
3981 "Missing `byte_order` attribute in trace (`trace` block).");
3982 ret = -EINVAL;
3983 goto error;
3984 }
3985
3986 return 0;
3987
3988 error:
3989 g_free(left);
3990 return ret;
3991 }
3992
3993 static int visit_clock_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *entry_node,
3994 struct ctf_clock_class *clock, int *set, int64_t *offset_seconds,
3995 uint64_t *offset_cycles)
3996 {
3997 int ret = 0;
3998 char *left = NULL;
3999
4000 if (entry_node->type != NODE_CTF_EXPRESSION) {
4001 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node, "Unexpected node type: node-type={}",
4002 entry_node->type);
4003 ret = -EPERM;
4004 goto error;
4005 }
4006
4007 left = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.left);
4008 if (!left) {
4009 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node, "Cannot concatenate unary strings.");
4010 ret = -EINVAL;
4011 goto error;
4012 }
4013
4014 if (strcmp(left, "name") == 0) {
4015 char *right;
4016
4017 if (_IS_SET(set, _CLOCK_NAME_SET)) {
4018 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "name", "clock class");
4019 ret = -EPERM;
4020 goto error;
4021 }
4022
4023 right = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.right);
4024 if (!right) {
4025 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4026 entry_node, "Unexpected unary expression for clock class's `name` attribute.");
4027 ret = -EINVAL;
4028 goto error;
4029 }
4030
4031 g_string_assign(clock->name, right);
4032 g_free(right);
4033 _SET(set, _CLOCK_NAME_SET);
4034 } else if (strcmp(left, "uuid") == 0) {
4035 bt_uuid_t uuid;
4036
4037 if (_IS_SET(set, _CLOCK_UUID_SET)) {
4038 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "uuid", "clock class");
4039 ret = -EPERM;
4040 goto error;
4041 }
4042
4043 ret = get_unary_uuid(ctx, &entry_node->u.ctf_expression.right, uuid);
4044 if (ret) {
4045 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node, "Invalid clock class's `uuid` attribute.");
4046 goto error;
4047 }
4048
4049 clock->has_uuid = true;
4050 bt_uuid_copy(clock->uuid, uuid);
4051 _SET(set, _CLOCK_UUID_SET);
4052 } else if (strcmp(left, "description") == 0) {
4053 char *right;
4054
4055 if (_IS_SET(set, _CLOCK_DESCRIPTION_SET)) {
4056 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "description", "clock class");
4057 ret = -EPERM;
4058 goto error;
4059 }
4060
4061 right = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.right);
4062 if (!right) {
4063 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4064 entry_node,
4065 "Unexpected unary expression for clock class's `description` attribute.");
4066 ret = -EINVAL;
4067 goto error;
4068 }
4069
4070 g_string_assign(clock->description, right);
4071 g_free(right);
4072 _SET(set, _CLOCK_DESCRIPTION_SET);
4073 } else if (strcmp(left, "freq") == 0) {
4074 uint64_t freq = UINT64_C(-1);
4075
4076 if (_IS_SET(set, _CLOCK_FREQ_SET)) {
4077 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "freq", "clock class");
4078 ret = -EPERM;
4079 goto error;
4080 }
4081
4082 ret = get_unary_unsigned(ctx, &entry_node->u.ctf_expression.right, &freq);
4083 if (ret) {
4084 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4085 entry_node, "Unexpected unary expression for clock class's `freq` attribute.");
4086 ret = -EINVAL;
4087 goto error;
4088 }
4089
4090 if (freq == UINT64_C(-1) || freq == 0) {
4091 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node, "Invalid clock class frequency: freq={}",
4092 freq);
4093 ret = -EINVAL;
4094 goto error;
4095 }
4096
4097 clock->frequency = freq;
4098 _SET(set, _CLOCK_FREQ_SET);
4099 } else if (strcmp(left, "precision") == 0) {
4100 uint64_t precision;
4101
4102 if (_IS_SET(set, _CLOCK_PRECISION_SET)) {
4103 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "precision", "clock class");
4104 ret = -EPERM;
4105 goto error;
4106 }
4107
4108 ret = get_unary_unsigned(ctx, &entry_node->u.ctf_expression.right, &precision);
4109 if (ret) {
4110 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4111 entry_node, "Unexpected unary expression for clock class's `precision` attribute.");
4112 ret = -EINVAL;
4113 goto error;
4114 }
4115
4116 clock->precision = precision;
4117 _SET(set, _CLOCK_PRECISION_SET);
4118 } else if (strcmp(left, "offset_s") == 0) {
4119 if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) {
4120 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "offset_s", "clock class");
4121 ret = -EPERM;
4122 goto error;
4123 }
4124
4125 ret = get_unary_signed(&entry_node->u.ctf_expression.right, offset_seconds);
4126 if (ret) {
4127 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4128 entry_node, "Unexpected unary expression for clock class's `offset_s` attribute.");
4129 ret = -EINVAL;
4130 goto error;
4131 }
4132
4133 _SET(set, _CLOCK_OFFSET_S_SET);
4134 } else if (strcmp(left, "offset") == 0) {
4135 if (_IS_SET(set, _CLOCK_OFFSET_SET)) {
4136 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "offset", "clock class");
4137 ret = -EPERM;
4138 goto error;
4139 }
4140
4141 ret = get_unary_unsigned(ctx, &entry_node->u.ctf_expression.right, offset_cycles);
4142 if (ret) {
4143 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4144 entry_node, "Unexpected unary expression for clock class's `offset` attribute.");
4145 ret = -EINVAL;
4146 goto error;
4147 }
4148
4149 _SET(set, _CLOCK_OFFSET_SET);
4150 } else if (strcmp(left, "absolute") == 0) {
4151 struct ctf_node *right;
4152
4153 if (_IS_SET(set, _CLOCK_ABSOLUTE_SET)) {
4154 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "absolute", "clock class");
4155 ret = -EPERM;
4156 goto error;
4157 }
4158
4159 right =
4160 _BT_LIST_FIRST_ENTRY(&entry_node->u.ctf_expression.right, struct ctf_node, siblings);
4161 ret = get_boolean(ctx, right);
4162 if (ret < 0) {
4163 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4164 entry_node, "Unexpected unary expression for clock class's `absolute` attribute.");
4165 ret = -EINVAL;
4166 goto error;
4167 }
4168
4169 clock->is_absolute = ret;
4170 _SET(set, _CLOCK_ABSOLUTE_SET);
4171 } else {
4172 _BT_CPPLOGW_NODE(entry_node, "Unknown attribute in clock class: attr-name=\"{}\"", left);
4173 }
4174
4175 g_free(left);
4176 left = NULL;
4177 return 0;
4178
4179 error:
4180 g_free(left);
4181 return ret;
4182 }
4183
4184 static inline uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns)
4185 {
4186 uint64_t cycles;
4187
4188 /* 1GHz */
4189 if (frequency == UINT64_C(1000000000)) {
4190 cycles = ns;
4191 } else {
4192 cycles = (uint64_t) (((double) ns * (double) frequency) / 1e9);
4193 }
4194
4195 return cycles;
4196 }
4197
4198 static void calibrate_clock_class_offsets(int64_t *offset_seconds, uint64_t *offset_cycles,
4199 uint64_t freq)
4200 {
4201 if (*offset_cycles >= freq) {
4202 const uint64_t s_in_offset_cycles = *offset_cycles / freq;
4203
4204 *offset_seconds += (int64_t) s_in_offset_cycles;
4205 *offset_cycles -= (s_in_offset_cycles * freq);
4206 }
4207 }
4208
4209 static void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir *ctx,
4210 struct ctf_clock_class *clock)
4211 {
4212 if (ctx->decoder_config.force_clock_class_origin_unix_epoch) {
4213 clock->is_absolute = true;
4214 }
4215
4216 return;
4217 }
4218
4219 static void apply_clock_class_offset(struct ctf_visitor_generate_ir *ctx,
4220 struct ctf_clock_class *clock)
4221 {
4222 uint64_t freq;
4223 int64_t offset_s_to_apply = ctx->decoder_config.clock_class_offset_s;
4224 uint64_t offset_ns_to_apply;
4225 int64_t cur_offset_s;
4226 uint64_t cur_offset_cycles;
4227
4228 if (ctx->decoder_config.clock_class_offset_s == 0 &&
4229 ctx->decoder_config.clock_class_offset_ns == 0) {
4230 goto end;
4231 }
4232
4233 /* Transfer nanoseconds to seconds as much as possible */
4234 if (ctx->decoder_config.clock_class_offset_ns < 0) {
4235 const int64_t abs_ns = -ctx->decoder_config.clock_class_offset_ns;
4236 const int64_t abs_extra_s = abs_ns / INT64_C(1000000000) + 1;
4237 const int64_t extra_s = -abs_extra_s;
4238 const int64_t offset_ns =
4239 ctx->decoder_config.clock_class_offset_ns - (extra_s * INT64_C(1000000000));
4240
4241 BT_ASSERT(offset_ns > 0);
4242 offset_ns_to_apply = (uint64_t) offset_ns;
4243 offset_s_to_apply += extra_s;
4244 } else {
4245 const int64_t extra_s = ctx->decoder_config.clock_class_offset_ns / INT64_C(1000000000);
4246 const int64_t offset_ns =
4247 ctx->decoder_config.clock_class_offset_ns - (extra_s * INT64_C(1000000000));
4248
4249 BT_ASSERT(offset_ns >= 0);
4250 offset_ns_to_apply = (uint64_t) offset_ns;
4251 offset_s_to_apply += extra_s;
4252 }
4253
4254 freq = clock->frequency;
4255 cur_offset_s = clock->offset_seconds;
4256 cur_offset_cycles = clock->offset_cycles;
4257
4258 /* Apply offsets */
4259 cur_offset_s += offset_s_to_apply;
4260 cur_offset_cycles += cycles_from_ns(freq, offset_ns_to_apply);
4261
4262 /*
4263 * Recalibrate offsets because the part in cycles can be greater
4264 * than the frequency at this point.
4265 */
4266 calibrate_clock_class_offsets(&cur_offset_s, &cur_offset_cycles, freq);
4267
4268 /* Set final offsets */
4269 clock->offset_seconds = cur_offset_s;
4270 clock->offset_cycles = cur_offset_cycles;
4271
4272 end:
4273 return;
4274 }
4275
4276 static int visit_clock_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *clock_node)
4277 {
4278 int ret = 0;
4279 int set = 0;
4280 struct ctf_clock_class *clock;
4281 struct ctf_node *entry_node;
4282 struct bt_list_head *decl_list = &clock_node->u.clock.declaration_list;
4283 const char *clock_class_name;
4284 int64_t offset_seconds = 0;
4285 uint64_t offset_cycles = 0;
4286 uint64_t freq;
4287
4288 if (clock_node->visited) {
4289 return 0;
4290 }
4291
4292 clock_node->visited = TRUE;
4293
4294 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4295 clock = ctf_clock_class_create();
4296 if (!clock) {
4297 _BT_CPPLOGE_APPEND_CAUSE_NODE(clock_node, "Cannot create default clock class.");
4298 ret = -ENOMEM;
4299 goto end;
4300 }
4301
4302 bt_list_for_each_entry (entry_node, decl_list, siblings) {
4303 ret = visit_clock_decl_entry(ctx, entry_node, clock, &set, &offset_seconds, &offset_cycles);
4304 if (ret) {
4305 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node, "Cannot visit clock class's entry: ret={}",
4306 ret);
4307 goto end;
4308 }
4309 }
4310
4311 if (!_IS_SET(&set, _CLOCK_NAME_SET)) {
4312 _BT_CPPLOGE_APPEND_CAUSE_NODE(clock_node, "Missing `name` attribute in clock class.");
4313 ret = -EPERM;
4314 goto end;
4315 }
4316
4317 clock_class_name = clock->name->str;
4318 BT_ASSERT(clock_class_name);
4319 if (ctx->is_lttng && strcmp(clock_class_name, "monotonic") == 0) {
4320 /*
4321 * Old versions of LTTng forgot to set its clock class
4322 * as absolute, even if it is. This is important because
4323 * it's a condition to be able to sort messages
4324 * from different sources.
4325 */
4326 clock->is_absolute = true;
4327 }
4328
4329 /*
4330 * Adjust offsets so that the part in cycles is less than the
4331 * frequency (move to the part in seconds).
4332 */
4333 freq = clock->frequency;
4334 calibrate_clock_class_offsets(&offset_seconds, &offset_cycles, freq);
4335 BT_ASSERT(offset_cycles < clock->frequency);
4336 clock->offset_seconds = offset_seconds;
4337 clock->offset_cycles = offset_cycles;
4338 apply_clock_class_offset(ctx, clock);
4339 apply_clock_class_is_absolute(ctx, clock);
4340 g_ptr_array_add(ctx->ctf_tc->clock_classes, clock);
4341 clock = NULL;
4342
4343 end:
4344 if (clock) {
4345 ctf_clock_class_destroy(clock);
4346 }
4347
4348 return ret;
4349 }
4350
4351 static int visit_root_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *root_decl_node)
4352 {
4353 int ret = 0;
4354
4355 if (root_decl_node->visited) {
4356 goto end;
4357 }
4358
4359 root_decl_node->visited = TRUE;
4360
4361 switch (root_decl_node->type) {
4362 case NODE_TYPEDEF:
4363 ret =
4364 visit_field_class_def(ctx, root_decl_node->u.field_class_def.field_class_specifier_list,
4365 &root_decl_node->u.field_class_def.field_class_declarators);
4366 if (ret) {
4367 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node,
4368 "Cannot add field class found in root scope.");
4369 goto end;
4370 }
4371 break;
4372 case NODE_TYPEALIAS:
4373 ret = visit_field_class_alias(ctx, root_decl_node->u.field_class_alias.target,
4374 root_decl_node->u.field_class_alias.alias);
4375 if (ret) {
4376 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node,
4377 "Cannot add field class alias found in root scope.");
4378 goto end;
4379 }
4380 break;
4381 case NODE_TYPE_SPECIFIER_LIST:
4382 {
4383 struct ctf_field_class *decl = NULL;
4384
4385 /*
4386 * Just add the field class specifier to the root
4387 * declaration scope. Put local reference.
4388 */
4389 ret = visit_field_class_specifier_list(ctx, root_decl_node, &decl);
4390 if (ret) {
4391 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node,
4392 "Cannot visit root scope's field class: "
4393 "ret={}",
4394 ret);
4395 BT_ASSERT(!decl);
4396 goto end;
4397 }
4398
4399 ctf_field_class_destroy(decl);
4400 decl = NULL;
4401 break;
4402 }
4403 default:
4404 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node, "Unexpected node type: node-type={}",
4405 root_decl_node->type);
4406 ret = -EPERM;
4407 goto end;
4408 }
4409
4410 end:
4411 return ret;
4412 }
4413
4414 struct ctf_visitor_generate_ir *
4415 ctf_visitor_generate_ir_create(const struct ctf_metadata_decoder_config *decoder_config)
4416 {
4417 struct ctf_visitor_generate_ir *ctx = NULL;
4418
4419 bt2c::Logger logger {decoder_config->logger, "PLUGIN/CTF/META/IR-VISITOR"};
4420
4421 /* Create visitor's context */
4422 ctx = ctx_create(decoder_config, logger);
4423 if (!ctx) {
4424 BT_CPPLOGE_APPEND_CAUSE_SPEC(logger, "Cannot create visitor's context.");
4425 goto error;
4426 }
4427
4428 goto end;
4429
4430 error:
4431 ctx_destroy(ctx);
4432 ctx = NULL;
4433
4434 end:
4435 return ctx;
4436 }
4437
4438 void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir *visitor)
4439 {
4440 ctx_destroy(visitor);
4441 }
4442
4443 bt_trace_class *ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir *ctx)
4444 {
4445 BT_ASSERT_DBG(ctx);
4446
4447 if (ctx->trace_class) {
4448 bt_trace_class_get_ref(ctx->trace_class);
4449 }
4450
4451 return ctx->trace_class;
4452 }
4453
4454 struct ctf_trace_class *
4455 ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir *ctx)
4456 {
4457 BT_ASSERT_DBG(ctx);
4458 BT_ASSERT_DBG(ctx->ctf_tc);
4459 return ctx->ctf_tc;
4460 }
4461
4462 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
4463 {
4464 int ret = 0;
4465
4466 BT_CPPLOGI_STR_SPEC(ctx->logger, "Visiting metadata's AST to generate CTF IR objects.");
4467
4468 switch (node->type) {
4469 case NODE_ROOT:
4470 {
4471 struct ctf_node *iter;
4472 bool got_trace_decl = false;
4473
4474 /*
4475 * The first thing we need is the native byte order of
4476 * the trace block, because early class aliases can have
4477 * a `byte_order` attribute set to `native`. If we don't
4478 * have the native byte order yet, and we don't have any
4479 * trace block yet, then fail with EINCOMPLETE.
4480 */
4481 if (ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_UNKNOWN) {
4482 bt_list_for_each_entry (iter, &node->u.root.trace, siblings) {
4483 if (got_trace_decl) {
4484 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Duplicate trace (`trace` block).");
4485 ret = -1;
4486 goto end;
4487 }
4488
4489 ret = set_trace_byte_order(ctx, iter);
4490 if (ret) {
4491 _BT_CPPLOGE_APPEND_CAUSE_NODE(node,
4492 "Cannot set trace's native byte order: "
4493 "ret={}",
4494 ret);
4495 goto end;
4496 }
4497
4498 got_trace_decl = true;
4499 }
4500
4501 if (!got_trace_decl) {
4502 BT_CPPLOGD_STR_SPEC(ctx->logger, "Incomplete AST: need trace (`trace` block).");
4503 ret = -EINCOMPLETE;
4504 goto end;
4505 }
4506 }
4507
4508 BT_ASSERT(ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_LITTLE ||
4509 ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_BIG);
4510 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4511
4512 /* Environment */
4513 bt_list_for_each_entry (iter, &node->u.root.env, siblings) {
4514 ret = visit_env(ctx, iter);
4515 if (ret) {
4516 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4517 iter,
4518 "Cannot visit trace's environment (`env` block) entry: "
4519 "ret={}",
4520 ret);
4521 goto end;
4522 }
4523 }
4524
4525 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4526
4527 /*
4528 * Visit clock blocks.
4529 */
4530 bt_list_for_each_entry (iter, &node->u.root.clock, siblings) {
4531 ret = visit_clock_decl(ctx, iter);
4532 if (ret) {
4533 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter, "Cannot visit clock class: ret={}", ret);
4534 goto end;
4535 }
4536 }
4537
4538 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4539
4540 /*
4541 * Visit root declarations next, as they can be used by any
4542 * following entity.
4543 */
4544 bt_list_for_each_entry (iter, &node->u.root.declaration_list, siblings) {
4545 ret = visit_root_decl(ctx, iter);
4546 if (ret) {
4547 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter, "Cannot visit root entry: ret={}", ret);
4548 goto end;
4549 }
4550 }
4551
4552 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4553
4554 /* Callsite blocks are not supported */
4555 bt_list_for_each_entry (iter, &node->u.root.callsite, siblings) {
4556 _BT_CPPLOGW_NODE(iter, "\"callsite\" blocks are not supported as of this version.");
4557 }
4558
4559 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4560
4561 /* Trace */
4562 bt_list_for_each_entry (iter, &node->u.root.trace, siblings) {
4563 ret = visit_trace_decl(ctx, iter);
4564 if (ret) {
4565 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter,
4566 "Cannot visit trace (`trace` block): "
4567 "ret={}",
4568 ret);
4569 goto end;
4570 }
4571 }
4572
4573 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4574
4575 /* Streams */
4576 bt_list_for_each_entry (iter, &node->u.root.stream, siblings) {
4577 ret = visit_stream_decl(ctx, iter);
4578 if (ret) {
4579 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter, "Cannot visit stream class: ret={}", ret);
4580 goto end;
4581 }
4582 }
4583
4584 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4585
4586 /* Events */
4587 bt_list_for_each_entry (iter, &node->u.root.event, siblings) {
4588 ret = visit_event_decl(ctx, iter);
4589 if (ret) {
4590 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter, "Cannot visit event class: ret={}", ret);
4591 goto end;
4592 }
4593 }
4594
4595 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4596 break;
4597 }
4598 default:
4599 _BT_CPPLOGE_APPEND_CAUSE_NODE(node, "Unexpected node type: node-type={}", node->type);
4600 ret = -EINVAL;
4601 goto end;
4602 }
4603
4604 /* Update default clock classes */
4605 ret = ctf_trace_class_update_default_clock_classes(ctx->ctf_tc, ctx->logger);
4606 if (ret) {
4607 ret = -EINVAL;
4608 goto end;
4609 }
4610
4611 /* Update trace class meanings */
4612 ret = ctf_trace_class_update_meanings(ctx->ctf_tc);
4613 if (ret) {
4614 ret = -EINVAL;
4615 goto end;
4616 }
4617
4618 /* Update stream class configuration */
4619 ret = ctf_trace_class_update_stream_class_config(ctx->ctf_tc);
4620 if (ret) {
4621 ret = -EINVAL;
4622 goto end;
4623 }
4624
4625 /* Update text arrays and sequences */
4626 ret = ctf_trace_class_update_text_array_sequence(ctx->ctf_tc);
4627 if (ret) {
4628 ret = -EINVAL;
4629 goto end;
4630 }
4631
4632 /* Update structure/array/sequence alignments */
4633 ret = ctf_trace_class_update_alignments(ctx->ctf_tc);
4634 if (ret) {
4635 ret = -EINVAL;
4636 goto end;
4637 }
4638
4639 /* Resolve sequence lengths and variant tags */
4640 ret = ctf_trace_class_resolve_field_classes(ctx->ctf_tc, ctx->logger);
4641 if (ret) {
4642 ret = -EINVAL;
4643 goto end;
4644 }
4645
4646 if (ctx->trace_class) {
4647 /*
4648 * Update "in IR" for field classes.
4649 *
4650 * If we have no IR trace class, then we'll have no way
4651 * to create IR fields anyway, so we leave all the
4652 * `in_ir` members false.
4653 */
4654 ret = ctf_trace_class_update_in_ir(ctx->ctf_tc);
4655 if (ret) {
4656 ret = -EINVAL;
4657 goto end;
4658 }
4659 }
4660
4661 /* Update saved value indexes */
4662 ret = ctf_trace_class_update_value_storing_indexes(ctx->ctf_tc);
4663 if (ret) {
4664 ret = -EINVAL;
4665 goto end;
4666 }
4667
4668 /* Validate what we have so far */
4669 ret = ctf_trace_class_validate(ctx->ctf_tc, ctx->logger);
4670 if (ret) {
4671 ret = -EINVAL;
4672 goto end;
4673 }
4674
4675 /*
4676 * If there are fields which are not related to the CTF format
4677 * itself in the packet header and in event header field
4678 * classes, warn about it because they are never translated.
4679 */
4680 ctf_trace_class_warn_meaningless_header_fields(ctx->ctf_tc, ctx->logger);
4681
4682 if (ctx->trace_class) {
4683 /* Copy new CTF metadata -> new IR metadata */
4684 ret =
4685 ctf_trace_class_translate(ctx->decoder_config.self_comp, ctx->trace_class, ctx->ctf_tc);
4686 if (ret) {
4687 ret = -EINVAL;
4688 goto end;
4689 }
4690 }
4691
4692 end:
4693 return ret;
4694 }
This page took 0.196339 seconds and 3 git commands to generate.