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