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