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