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