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