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