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