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