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