2 * SPDX-License-Identifier: MIT
4 * Copyright 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * Copyright 2015-2018 Philippe Proulx <philippe.proulx@efficios.com>
7 * Common Trace Format metadata visitor (generates CTF IR objects).
10 #define BT_COMP_LOG_SELF_COMP (ctx->log_cfg.self_comp)
11 #define BT_COMP_LOG_SELF_COMP_CLASS (ctx->log_cfg.self_comp_class)
12 #define BT_LOG_OUTPUT_LEVEL (ctx->log_cfg.log_level)
13 #define BT_LOG_TAG "PLUGIN/CTF/META/IR-VISITOR"
14 #include "logging/comp-logging.h"
22 #include "common/assert.h"
26 #include "common/common.h"
27 #include "common/uuid.h"
28 #include "compat/endian.h"
29 #include <babeltrace2/babeltrace.h>
31 #include "logging.hpp"
32 #include "scanner.hpp"
34 #include "decoder.hpp"
35 #include "ctf-meta.hpp"
36 #include "ctf-meta-visitors.hpp"
38 /* Bit value (left shift) */
39 #define _BV(_val) (1 << (_val))
41 /* Bit is set in a set of bits */
42 #define _IS_SET(_set, _mask) (*(_set) & (_mask))
44 /* Set bit in a set of bits */
45 #define _SET(_set, _mask) (*(_set) |= (_mask))
47 /* Try to push scope, or go to the `error` label */
48 #define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
50 ret = ctx_push_scope(ctx); \
52 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot push scope."); \
57 /* Bits for verifying existing attributes in various declarations */
60 _CLOCK_NAME_SET
= _BV(0),
61 _CLOCK_UUID_SET
= _BV(1),
62 _CLOCK_FREQ_SET
= _BV(2),
63 _CLOCK_PRECISION_SET
= _BV(3),
64 _CLOCK_OFFSET_S_SET
= _BV(4),
65 _CLOCK_OFFSET_SET
= _BV(5),
66 _CLOCK_ABSOLUTE_SET
= _BV(6),
67 _CLOCK_DESCRIPTION_SET
= _BV(7),
72 _INTEGER_ALIGN_SET
= _BV(0),
73 _INTEGER_SIZE_SET
= _BV(1),
74 _INTEGER_BASE_SET
= _BV(2),
75 _INTEGER_ENCODING_SET
= _BV(3),
76 _INTEGER_BYTE_ORDER_SET
= _BV(4),
77 _INTEGER_SIGNED_SET
= _BV(5),
78 _INTEGER_MAP_SET
= _BV(6),
83 _FLOAT_ALIGN_SET
= _BV(0),
84 _FLOAT_MANT_DIG_SET
= _BV(1),
85 _FLOAT_EXP_DIG_SET
= _BV(2),
86 _FLOAT_BYTE_ORDER_SET
= _BV(3),
91 _STRING_ENCODING_SET
= _BV(0),
96 _TRACE_MINOR_SET
= _BV(0),
97 _TRACE_MAJOR_SET
= _BV(1),
98 _TRACE_BYTE_ORDER_SET
= _BV(2),
99 _TRACE_UUID_SET
= _BV(3),
100 _TRACE_PACKET_HEADER_SET
= _BV(4),
105 _STREAM_ID_SET
= _BV(0),
106 _STREAM_PACKET_CONTEXT_SET
= _BV(1),
107 _STREAM_EVENT_HEADER_SET
= _BV(2),
108 _STREAM_EVENT_CONTEXT_SET
= _BV(3),
113 _EVENT_NAME_SET
= _BV(0),
114 _EVENT_ID_SET
= _BV(1),
115 _EVENT_MODEL_EMF_URI_SET
= _BV(2),
116 _EVENT_STREAM_ID_SET
= _BV(3),
117 _EVENT_LOG_LEVEL_SET
= _BV(4),
118 _EVENT_CONTEXT_SET
= _BV(5),
119 _EVENT_FIELDS_SET
= _BV(6),
128 LOG_LEVEL_WARNING
= 4,
129 LOG_LEVEL_NOTICE
= 5,
131 LOG_LEVEL_DEBUG_SYSTEM
= 7,
132 LOG_LEVEL_DEBUG_PROGRAM
= 8,
133 LOG_LEVEL_DEBUG_PROCESS
= 9,
134 LOG_LEVEL_DEBUG_MODULE
= 10,
135 LOG_LEVEL_DEBUG_UNIT
= 11,
136 LOG_LEVEL_DEBUG_FUNCTION
= 12,
137 LOG_LEVEL_DEBUG_LINE
= 13,
138 LOG_LEVEL_DEBUG
= 14,
142 /* Prefixes of class aliases */
143 #define _PREFIX_ALIAS 'a'
144 #define _PREFIX_ENUM 'e'
145 #define _PREFIX_STRUCT 's'
146 #define _PREFIX_VARIANT 'v'
148 /* First entry in a BT list */
149 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) bt_list_entry((_ptr)->next, _class, _member)
151 #define _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \
152 _BT_COMP_LOGE_APPEND_CAUSE_LINENO( \
153 (_node)->lineno, "Duplicate attribute in %s: attr-name=\"%s\"", _entity, _attr)
155 #define _BT_COMP_LOGE_NODE(_node, _msg, args...) _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ##args)
157 #define _BT_COMP_LOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
158 _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, _msg, ##args)
160 #define _BT_COMP_LOGW_NODE(_node, _msg, args...) _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ##args)
162 #define _BT_COMP_LOGT_NODE(_node, _msg, args...) _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ##args)
165 * Declaration scope of a visitor context. This represents a TSDL
166 * lexical scope, so that aliases and named structures, variants,
167 * and enumerations may be registered and looked up hierarchically.
169 struct ctx_decl_scope
172 * Alias name to field class.
174 * GQuark -> struct ctf_field_class * (owned by this)
176 GHashTable
*decl_map
;
178 /* Parent scope; NULL if this is the root declaration scope */
179 struct ctx_decl_scope
*parent_scope
;
183 * Visitor context (private).
185 struct ctf_visitor_generate_ir
187 struct meta_log_config log_cfg
;
189 /* Trace IR trace class being filled (owned by this) */
190 bt_trace_class
*trace_class
;
192 /* CTF meta trace being filled (owned by this) */
193 struct ctf_trace_class
*ctf_tc
;
195 /* Current declaration scope (top of the stack) (owned by this) */
196 struct ctx_decl_scope
*current_scope
;
198 /* True if trace declaration is visited */
199 bool is_trace_visited
;
201 /* True if this is an LTTng trace */
204 /* Config passed by the user */
205 struct ctf_metadata_decoder_config decoder_config
;
211 struct ctf_visitor_generate_ir
;
214 * Creates a new declaration scope.
216 * @param par_scope Parent scope (NULL if creating a root scope)
217 * @returns New declaration scope, or NULL on error
219 static struct ctx_decl_scope
*ctx_decl_scope_create(struct ctf_visitor_generate_ir
*ctx
,
220 struct ctx_decl_scope
*par_scope
)
222 struct ctx_decl_scope
*scope
;
224 scope
= g_new(struct ctx_decl_scope
, 1);
226 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate one declaration scope.");
230 scope
->decl_map
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
,
231 (GDestroyNotify
) ctf_field_class_destroy
);
232 scope
->parent_scope
= par_scope
;
239 * Destroys a declaration scope.
241 * This function does not destroy the parent scope.
243 * @param scope Scope to destroy
245 static void ctx_decl_scope_destroy(struct ctx_decl_scope
*scope
)
251 g_hash_table_destroy(scope
->decl_map
);
259 * Returns the GQuark of a prefixed alias.
261 * @param prefix Prefix character
263 * @returns Associated GQuark, or 0 on error
265 static GQuark
get_prefixed_named_quark(struct ctf_visitor_generate_ir
*ctx
, char prefix
,
272 /* Prefix character + original string + '\0' */
273 char *prname
= g_new(char, strlen(name
) + 2);
275 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate a string.");
279 sprintf(prname
, "%c%s", prefix
, name
);
280 qname
= g_quark_from_string(prname
);
288 * Looks up a prefixed class alias within a declaration scope.
290 * @param scope Declaration scope
291 * @param prefix Prefix character
292 * @param name Alias name
293 * @param levels Number of levels to dig into (-1 means infinite)
294 * @param copy True to return a copy
295 * @returns Declaration (owned by caller if \p copy is true),
296 * or NULL if not found
298 static struct ctf_field_class
*
299 ctx_decl_scope_lookup_prefix_alias(struct ctf_visitor_generate_ir
*ctx
,
300 struct ctx_decl_scope
*scope
, char prefix
, const char *name
,
301 int levels
, bool copy
)
305 struct ctf_field_class
*decl
= NULL
;
306 struct ctx_decl_scope
*cur_scope
= scope
;
310 qname
= get_prefixed_named_quark(ctx
, prefix
, name
);
319 while (cur_scope
&& cur_levels
< levels
) {
320 decl
= (ctf_field_class
*) g_hash_table_lookup(cur_scope
->decl_map
,
321 (gconstpointer
) GUINT_TO_POINTER(qname
));
323 /* Caller's reference */
325 decl
= ctf_field_class_copy(decl
);
332 cur_scope
= cur_scope
->parent_scope
;
341 * Looks up a class alias within a declaration scope.
343 * @param scope Declaration scope
344 * @param name Alias name
345 * @param levels Number of levels to dig into (-1 means infinite)
346 * @param copy True to return a copy
347 * @returns Declaration (owned by caller if \p copy is true),
348 * or NULL if not found
350 static struct ctf_field_class
*ctx_decl_scope_lookup_alias(struct ctf_visitor_generate_ir
*ctx
,
351 struct ctx_decl_scope
*scope
,
352 const char *name
, int levels
, bool copy
)
354 return ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, _PREFIX_ALIAS
, name
, levels
, copy
);
358 * Looks up an enumeration within a declaration scope.
360 * @param scope Declaration scope
361 * @param name Enumeration name
362 * @param levels Number of levels to dig into (-1 means infinite)
363 * @param copy True to return a copy
364 * @returns Declaration (owned by caller if \p copy is true),
365 * or NULL if not found
367 static struct ctf_field_class_enum
*ctx_decl_scope_lookup_enum(struct ctf_visitor_generate_ir
*ctx
,
368 struct ctx_decl_scope
*scope
,
369 const char *name
, int levels
,
372 return ctf_field_class_as_enum(
373 ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, _PREFIX_ENUM
, name
, levels
, copy
));
377 * Looks up a structure within a declaration scope.
379 * @param scope Declaration scope
380 * @param name Structure name
381 * @param levels Number of levels to dig into (-1 means infinite)
382 * @param copy True to return a copy
383 * @returns Declaration (owned by caller if \p copy is true),
384 * or NULL if not found
386 static struct ctf_field_class_struct
*
387 ctx_decl_scope_lookup_struct(struct ctf_visitor_generate_ir
*ctx
, struct ctx_decl_scope
*scope
,
388 const char *name
, int levels
, bool copy
)
390 return ctf_field_class_as_struct(
391 ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, _PREFIX_STRUCT
, name
, levels
, copy
));
395 * Looks up a variant within a declaration scope.
397 * @param scope Declaration scope
398 * @param name Variant name
399 * @param levels Number of levels to dig into (-1 means infinite)
400 * @param copy True to return a copy
401 * @returns Declaration (owned by caller if \p copy is true),
402 * or NULL if not found
404 static struct ctf_field_class_variant
*
405 ctx_decl_scope_lookup_variant(struct ctf_visitor_generate_ir
*ctx
, struct ctx_decl_scope
*scope
,
406 const char *name
, int levels
, bool copy
)
408 return ctf_field_class_as_variant(
409 ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, _PREFIX_VARIANT
, name
, levels
, copy
));
413 * Registers a prefixed class alias within a declaration scope.
415 * @param scope Declaration scope
416 * @param prefix Prefix character
417 * @param name Alias name (non-NULL)
418 * @param decl Field class to register (copied)
419 * @returns 0 if registration went okay, negative value otherwise
421 static int ctx_decl_scope_register_prefix_alias(struct ctf_visitor_generate_ir
*ctx
,
422 struct ctx_decl_scope
*scope
, char prefix
,
423 const char *name
, struct ctf_field_class
*decl
)
431 qname
= get_prefixed_named_quark(ctx
, prefix
, name
);
437 /* Make sure alias does not exist in local scope */
438 if (ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, prefix
, name
, 1, false)) {
443 decl
= ctf_field_class_copy(decl
);
445 g_hash_table_insert(scope
->decl_map
, GUINT_TO_POINTER(qname
), decl
);
452 * Registers a class alias within a declaration scope.
454 * @param scope Declaration scope
455 * @param name Alias name (non-NULL)
456 * @param decl Field class to register (copied)
457 * @returns 0 if registration went okay, negative value otherwise
459 static int ctx_decl_scope_register_alias(struct ctf_visitor_generate_ir
*ctx
,
460 struct ctx_decl_scope
*scope
, const char *name
,
461 struct ctf_field_class
*decl
)
463 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_ALIAS
, name
, decl
);
467 * Registers an enumeration declaration within a declaration scope.
469 * @param scope Declaration scope
470 * @param name Enumeration name (non-NULL)
471 * @param decl Enumeration field class to register (copied)
472 * @returns 0 if registration went okay, negative value otherwise
474 static int ctx_decl_scope_register_enum(struct ctf_visitor_generate_ir
*ctx
,
475 struct ctx_decl_scope
*scope
, const char *name
,
476 struct ctf_field_class_enum
*decl
)
478 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_ENUM
, name
,
479 &decl
->base
.base
.base
);
483 * Registers a structure declaration within a declaration scope.
485 * @param scope Declaration scope
486 * @param name Structure name (non-NULL)
487 * @param decl Structure field class to register (copied)
488 * @returns 0 if registration went okay, negative value otherwise
490 static int ctx_decl_scope_register_struct(struct ctf_visitor_generate_ir
*ctx
,
491 struct ctx_decl_scope
*scope
, const char *name
,
492 struct ctf_field_class_struct
*decl
)
494 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_STRUCT
, name
, &decl
->base
);
498 * Registers a variant declaration within a declaration scope.
500 * @param scope Declaration scope
501 * @param name Variant name (non-NULL)
502 * @param decl Variant field class to register
503 * @returns 0 if registration went okay, negative value otherwise
505 static int ctx_decl_scope_register_variant(struct ctf_visitor_generate_ir
*ctx
,
506 struct ctx_decl_scope
*scope
, const char *name
,
507 struct ctf_field_class_variant
*decl
)
509 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_VARIANT
, name
, &decl
->base
);
513 * Destroys a visitor context.
515 * @param ctx Visitor context to destroy
517 static void ctx_destroy(struct ctf_visitor_generate_ir
*ctx
)
519 struct ctx_decl_scope
*scope
;
525 scope
= ctx
->current_scope
;
528 * Destroy all scopes, from current one to the root scope.
531 struct ctx_decl_scope
*parent_scope
= scope
->parent_scope
;
533 ctx_decl_scope_destroy(scope
);
534 scope
= parent_scope
;
537 bt_trace_class_put_ref(ctx
->trace_class
);
540 ctf_trace_class_destroy(ctx
->ctf_tc
);
550 * Creates a new visitor context.
552 * @param trace Associated trace
553 * @returns New visitor context, or NULL on error
555 static struct ctf_visitor_generate_ir
*
556 ctx_create(const struct ctf_metadata_decoder_config
*decoder_config
)
558 struct ctf_visitor_generate_ir
*ctx
= NULL
;
560 BT_ASSERT(decoder_config
);
562 ctx
= g_new0(struct ctf_visitor_generate_ir
, 1);
564 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
, decoder_config
->self_comp
,
565 "Failed to allocate one visitor context.");
569 ctx
->log_cfg
.log_level
= decoder_config
->log_level
;
570 ctx
->log_cfg
.self_comp
= decoder_config
->self_comp
;
571 ctx
->log_cfg
.self_comp_class
= decoder_config
->self_comp_class
;
573 if (decoder_config
->self_comp
) {
574 ctx
->trace_class
= bt_trace_class_create(decoder_config
->self_comp
);
575 if (!ctx
->trace_class
) {
576 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create empty trace class.");
581 ctx
->ctf_tc
= ctf_trace_class_create();
583 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create CTF trace class.");
587 /* Root declaration scope */
588 ctx
->current_scope
= ctx_decl_scope_create(ctx
, NULL
);
589 if (!ctx
->current_scope
) {
590 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
594 ctx
->decoder_config
= *decoder_config
;
606 * Pushes a new declaration scope on top of a visitor context's
607 * declaration scope stack.
609 * @param ctx Visitor context
610 * @returns 0 on success, or a negative value on error
612 static int ctx_push_scope(struct ctf_visitor_generate_ir
*ctx
)
615 struct ctx_decl_scope
*new_scope
;
618 new_scope
= ctx_decl_scope_create(ctx
, ctx
->current_scope
);
620 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
625 ctx
->current_scope
= new_scope
;
631 static void ctx_pop_scope(struct ctf_visitor_generate_ir
*ctx
)
633 struct ctx_decl_scope
*parent_scope
= NULL
;
637 if (!ctx
->current_scope
) {
641 parent_scope
= ctx
->current_scope
->parent_scope
;
642 ctx_decl_scope_destroy(ctx
->current_scope
);
643 ctx
->current_scope
= parent_scope
;
649 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
650 struct ctf_node
*ts_list
,
651 struct ctf_field_class
**decl
);
653 static int is_unary_string(struct bt_list_head
*head
)
656 struct ctf_node
*node
;
658 bt_list_for_each_entry (node
, head
, siblings
) {
659 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
663 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
671 static const char *get_map_clock_name_value(struct bt_list_head
*head
)
674 struct ctf_node
*node
;
675 const char *name
= NULL
;
677 bt_list_for_each_entry (node
, head
, siblings
) {
679 int uexpr_type
= node
->u
.unary_expression
.type
;
680 int uexpr_link
= node
->u
.unary_expression
.link
;
681 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_STRING
||
682 !((uexpr_link
!= UNARY_LINK_UNKNOWN
) ^ (i
== 0));
687 /* Needs to be chained with . */
688 switch (node
->u
.unary_expression
.link
) {
691 case UNARY_ARROWLINK
:
692 case UNARY_DOTDOTDOT
:
698 src_string
= node
->u
.unary_expression
.u
.string
;
702 if (strcmp("clock", src_string
)) {
710 if (strcmp("value", src_string
)) {
715 /* Extra identifier, unknown */
728 static int is_unary_unsigned(struct bt_list_head
*head
)
731 struct ctf_node
*node
;
733 bt_list_for_each_entry (node
, head
, siblings
) {
734 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
738 if (node
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
746 static int get_unary_unsigned(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
751 struct ctf_node
*node
;
755 if (bt_list_empty(head
)) {
760 bt_list_for_each_entry (node
, head
, siblings
) {
761 int uexpr_type
= node
->u
.unary_expression
.type
;
762 int uexpr_link
= node
->u
.unary_expression
.link
;
763 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_UNSIGNED_CONSTANT
||
764 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
766 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid constant unsigned integer.");
771 *value
= node
->u
.unary_expression
.u
.unsigned_constant
;
779 static int is_unary_signed(struct bt_list_head
*head
)
782 struct ctf_node
*node
;
784 bt_list_for_each_entry (node
, head
, siblings
) {
785 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
789 if (node
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
) {
797 static int get_unary_signed(struct bt_list_head
*head
, int64_t *value
)
801 struct ctf_node
*node
;
803 bt_list_for_each_entry (node
, head
, siblings
) {
804 int uexpr_type
= node
->u
.unary_expression
.type
;
805 int uexpr_link
= node
->u
.unary_expression
.link
;
806 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
807 (uexpr_type
!= UNARY_UNSIGNED_CONSTANT
&& uexpr_type
!= UNARY_SIGNED_CONSTANT
) ||
808 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
814 switch (uexpr_type
) {
815 case UNARY_UNSIGNED_CONSTANT
:
816 *value
= (int64_t) node
->u
.unary_expression
.u
.unsigned_constant
;
818 case UNARY_SIGNED_CONSTANT
:
819 *value
= node
->u
.unary_expression
.u
.signed_constant
;
833 static int get_unary_uuid(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
836 return ctf_ast_get_unary_uuid(head
, uuid
, ctx
->log_cfg
.log_level
, ctx
->log_cfg
.self_comp
);
839 static int get_boolean(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*unary_expr
)
843 if (unary_expr
->type
!= NODE_UNARY_EXPRESSION
) {
844 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
, "Expecting unary expression: node-type=%d",
850 switch (unary_expr
->u
.unary_expression
.type
) {
851 case UNARY_UNSIGNED_CONSTANT
:
852 ret
= (unary_expr
->u
.unary_expression
.u
.unsigned_constant
!= 0);
854 case UNARY_SIGNED_CONSTANT
:
855 ret
= (unary_expr
->u
.unary_expression
.u
.signed_constant
!= 0);
859 const char *str
= unary_expr
->u
.unary_expression
.u
.string
;
861 if (strcmp(str
, "true") == 0 || strcmp(str
, "TRUE") == 0) {
863 } else if (strcmp(str
, "false") == 0 || strcmp(str
, "FALSE") == 0) {
866 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
, "Unexpected boolean value: value=\"%s\"",
874 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
875 "Unexpected unary expression type: node-type=%d",
876 unary_expr
->u
.unary_expression
.type
);
885 static enum ctf_byte_order
byte_order_from_unary_expr(struct ctf_visitor_generate_ir
*ctx
,
886 struct ctf_node
*unary_expr
)
889 enum ctf_byte_order bo
= CTF_BYTE_ORDER_UNKNOWN
;
891 if (unary_expr
->u
.unary_expression
.type
!= UNARY_STRING
) {
892 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
893 unary_expr
, "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
897 str
= unary_expr
->u
.unary_expression
.u
.string
;
899 if (strcmp(str
, "be") == 0 || strcmp(str
, "network") == 0) {
900 bo
= CTF_BYTE_ORDER_BIG
;
901 } else if (strcmp(str
, "le") == 0) {
902 bo
= CTF_BYTE_ORDER_LITTLE
;
903 } else if (strcmp(str
, "native") == 0) {
904 bo
= CTF_BYTE_ORDER_DEFAULT
;
906 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
908 "Unexpected \"byte_order\" attribute value: "
909 "expecting `be`, `le`, `network`, or `native`: value=\"%s\"",
918 static enum ctf_byte_order
get_real_byte_order(struct ctf_visitor_generate_ir
*ctx
,
919 struct ctf_node
*uexpr
)
921 enum ctf_byte_order bo
= byte_order_from_unary_expr(ctx
, uexpr
);
923 if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
924 bo
= ctx
->ctf_tc
->default_byte_order
;
930 static int is_align_valid(uint64_t align
)
932 return (align
!= 0) && !(align
& (align
- UINT64_C(1)));
935 static int get_class_specifier_name(struct ctf_visitor_generate_ir
*ctx
,
936 struct ctf_node
*cls_specifier
, GString
*str
)
940 if (cls_specifier
->type
!= NODE_TYPE_SPECIFIER
) {
941 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
, "Unexpected node type: node-type=%d",
942 cls_specifier
->type
);
947 switch (cls_specifier
->u
.field_class_specifier
.type
) {
949 g_string_append(str
, "void");
952 g_string_append(str
, "char");
955 g_string_append(str
, "short");
958 g_string_append(str
, "int");
961 g_string_append(str
, "long");
964 g_string_append(str
, "float");
966 case TYPESPEC_DOUBLE
:
967 g_string_append(str
, "double");
969 case TYPESPEC_SIGNED
:
970 g_string_append(str
, "signed");
972 case TYPESPEC_UNSIGNED
:
973 g_string_append(str
, "unsigned");
976 g_string_append(str
, "bool");
978 case TYPESPEC_COMPLEX
:
979 g_string_append(str
, "_Complex");
981 case TYPESPEC_IMAGINARY
:
982 g_string_append(str
, "_Imaginary");
985 g_string_append(str
, "const");
987 case TYPESPEC_ID_TYPE
:
988 if (cls_specifier
->u
.field_class_specifier
.id_type
) {
989 g_string_append(str
, cls_specifier
->u
.field_class_specifier
.id_type
);
992 case TYPESPEC_STRUCT
:
994 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
996 if (!node
->u
._struct
.name
) {
997 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty structure field class name.");
1002 g_string_append(str
, "struct ");
1003 g_string_append(str
, node
->u
._struct
.name
);
1006 case TYPESPEC_VARIANT
:
1008 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1010 if (!node
->u
.variant
.name
) {
1011 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty variant field class name.");
1016 g_string_append(str
, "variant ");
1017 g_string_append(str
, node
->u
.variant
.name
);
1022 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1024 if (!node
->u
._enum
.enum_id
) {
1025 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1026 node
, "Unexpected empty enumeration field class (`enum`) name.");
1031 g_string_append(str
, "enum ");
1032 g_string_append(str
, node
->u
._enum
.enum_id
);
1035 case TYPESPEC_FLOATING_POINT
:
1036 case TYPESPEC_INTEGER
:
1037 case TYPESPEC_STRING
:
1039 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
->u
.field_class_specifier
.node
,
1040 "Unexpected field class specifier type: %d",
1041 cls_specifier
->u
.field_class_specifier
.type
);
1050 static int get_class_specifier_list_name(struct ctf_visitor_generate_ir
*ctx
,
1051 struct ctf_node
*cls_specifier_list
, GString
*str
)
1054 struct ctf_node
*iter
;
1055 int alias_item_nr
= 0;
1056 struct bt_list_head
*head
= &cls_specifier_list
->u
.field_class_specifier_list
.head
;
1058 bt_list_for_each_entry (iter
, head
, siblings
) {
1059 if (alias_item_nr
!= 0) {
1060 g_string_append(str
, " ");
1064 ret
= get_class_specifier_name(ctx
, iter
, str
);
1074 static GQuark
create_class_alias_identifier(struct ctf_visitor_generate_ir
*ctx
,
1075 struct ctf_node
*cls_specifier_list
,
1076 struct ctf_node
*node_field_class_declarator
)
1082 struct ctf_node
*iter
;
1083 struct bt_list_head
*pointers
= &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1085 str
= g_string_new("");
1086 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
1088 g_string_free(str
, TRUE
);
1092 bt_list_for_each_entry (iter
, pointers
, siblings
) {
1093 g_string_append(str
, " *");
1095 if (iter
->u
.pointer
.const_qualifier
) {
1096 g_string_append(str
, " const");
1100 str_c
= g_string_free(str
, FALSE
);
1101 qalias
= g_quark_from_string(str_c
);
1108 static int visit_field_class_declarator(struct ctf_visitor_generate_ir
*ctx
,
1109 struct ctf_node
*cls_specifier_list
, GQuark
*field_name
,
1110 struct ctf_node
*node_field_class_declarator
,
1111 struct ctf_field_class
**field_decl
,
1112 struct ctf_field_class
*nested_decl
)
1115 * During this whole function, nested_decl is always OURS,
1116 * whereas field_decl is an output which we create, but
1117 * belongs to the caller (it is moved).
1122 /* Validate field class declarator node */
1123 if (node_field_class_declarator
) {
1124 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_UNKNOWN
) {
1125 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1126 node_field_class_declarator
, "Unexpected field class declarator type: type=%d",
1127 node_field_class_declarator
->u
.field_class_declarator
.type
);
1132 /* TODO: GCC bitfields not supported yet */
1133 if (node_field_class_declarator
->u
.field_class_declarator
.bitfield_len
!= NULL
) {
1134 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1135 "GCC bitfields are not supported as of this version.");
1141 /* Find the right nested declaration if not provided */
1143 struct bt_list_head
*pointers
=
1144 &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1146 if (node_field_class_declarator
&& !bt_list_empty(pointers
)) {
1150 * If we have a pointer declarator, it HAS to
1151 * be present in the field class aliases (else
1155 create_class_alias_identifier(ctx
, cls_specifier_list
, node_field_class_declarator
);
1156 nested_decl
= ctx_decl_scope_lookup_alias(ctx
, ctx
->current_scope
,
1157 g_quark_to_string(qalias
), -1, true);
1159 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1160 "Cannot find class alias: name=\"%s\"",
1161 g_quark_to_string(qalias
));
1166 if (nested_decl
->type
== CTF_FIELD_CLASS_TYPE_INT
) {
1167 /* Pointer: force integer's base to 16 */
1168 struct ctf_field_class_int
*int_fc
= ctf_field_class_as_int(nested_decl
);
1170 int_fc
->disp_base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
1173 ret
= visit_field_class_specifier_list(ctx
, cls_specifier_list
, &nested_decl
);
1175 BT_ASSERT(!nested_decl
);
1181 BT_ASSERT(nested_decl
);
1183 if (!node_field_class_declarator
) {
1184 *field_decl
= nested_decl
;
1189 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_ID
) {
1190 if (node_field_class_declarator
->u
.field_class_declarator
.u
.id
) {
1191 const char *id
= node_field_class_declarator
->u
.field_class_declarator
.u
.id
;
1193 *field_name
= g_quark_from_string(id
);
1198 *field_decl
= nested_decl
;
1202 struct ctf_node
*first
;
1203 struct ctf_field_class
*decl
= NULL
;
1204 struct ctf_field_class
*outer_field_decl
= NULL
;
1205 struct bt_list_head
*length
=
1206 &node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.length
;
1208 /* Create array/sequence, pass nested_decl as child */
1209 if (bt_list_empty(length
)) {
1210 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1211 "Expecting length field reference or value.");
1216 first
= _BT_LIST_FIRST_ENTRY(length
, struct ctf_node
, siblings
);
1217 if (first
->type
!= NODE_UNARY_EXPRESSION
) {
1218 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type=%d",
1224 switch (first
->u
.unary_expression
.type
) {
1225 case UNARY_UNSIGNED_CONSTANT
:
1227 struct ctf_field_class_array
*array_decl
= NULL
;
1229 array_decl
= ctf_field_class_array_create();
1230 BT_ASSERT(array_decl
);
1231 array_decl
->length
= first
->u
.unary_expression
.u
.unsigned_constant
;
1232 array_decl
->base
.elem_fc
= nested_decl
;
1234 decl
= &array_decl
->base
.base
;
1239 /* Lookup unsigned integer definition, create seq. */
1240 struct ctf_field_class_sequence
*seq_decl
= NULL
;
1241 char *length_name
= ctf_ast_concatenate_unary_strings(length
);
1244 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1245 "Cannot concatenate unary strings.");
1250 if (strncmp(length_name
, "env.", 4) == 0) {
1251 /* This is, in fact, an array */
1252 const char *env_entry_name
= &length_name
[4];
1253 struct ctf_trace_class_env_entry
*env_entry
=
1254 ctf_trace_class_borrow_env_entry_by_name(ctx
->ctf_tc
, env_entry_name
);
1255 struct ctf_field_class_array
*array_decl
;
1258 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1259 "Cannot find environment entry: "
1266 if (env_entry
->type
!= CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
) {
1267 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1268 "Wrong environment entry type "
1269 "(expecting integer): "
1276 if (env_entry
->value
.i
< 0) {
1277 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1278 "Invalid, negative array length: "
1279 "env-entry-name=\"%s\", "
1281 env_entry_name
, env_entry
->value
.i
);
1286 array_decl
= ctf_field_class_array_create();
1287 BT_ASSERT(array_decl
);
1288 array_decl
->length
= (uint64_t) env_entry
->value
.i
;
1289 array_decl
->base
.elem_fc
= nested_decl
;
1291 decl
= &array_decl
->base
.base
;
1293 seq_decl
= ctf_field_class_sequence_create();
1294 BT_ASSERT(seq_decl
);
1295 seq_decl
->base
.elem_fc
= nested_decl
;
1297 g_string_assign(seq_decl
->length_ref
, length_name
);
1298 decl
= &seq_decl
->base
.base
;
1301 g_free(length_name
);
1309 BT_ASSERT(!nested_decl
);
1311 BT_ASSERT(!*field_decl
);
1314 * At this point, we found the next nested declaration.
1315 * We currently own this (and lost the ownership of
1316 * nested_decl in the meantime). Pass this next
1317 * nested declaration as the content of the outer
1318 * container, MOVING its ownership.
1320 ret
= visit_field_class_declarator(
1321 ctx
, cls_specifier_list
, field_name
,
1322 node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.field_class_declarator
,
1323 &outer_field_decl
, decl
);
1326 BT_ASSERT(!outer_field_decl
);
1331 BT_ASSERT(outer_field_decl
);
1332 *field_decl
= outer_field_decl
;
1333 outer_field_decl
= NULL
;
1336 BT_ASSERT(*field_decl
);
1340 ctf_field_class_destroy(*field_decl
);
1348 ctf_field_class_destroy(nested_decl
);
1353 static int visit_struct_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1354 struct ctf_field_class_struct
*struct_decl
,
1355 struct ctf_node
*cls_specifier_list
,
1356 struct bt_list_head
*field_class_declarators
)
1359 struct ctf_node
*iter
;
1360 struct ctf_field_class
*field_decl
= NULL
;
1362 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1365 const char *field_name
;
1367 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1370 BT_ASSERT(!field_decl
);
1371 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1372 "Cannot visit field class declarator: ret=%d", ret
);
1376 BT_ASSERT(field_decl
);
1377 field_name
= g_quark_to_string(qfield_name
);
1379 /* Check if field with same name already exists */
1380 if (ctf_field_class_struct_borrow_member_by_name(struct_decl
, field_name
)) {
1381 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1382 "Duplicate field in structure field class: "
1383 "field-name=\"%s\"",
1389 /* Add field to structure */
1390 ctf_field_class_struct_append_member(struct_decl
, field_name
, field_decl
);
1397 ctf_field_class_destroy(field_decl
);
1402 static int visit_variant_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1403 struct ctf_field_class_variant
*variant_decl
,
1404 struct ctf_node
*cls_specifier_list
,
1405 struct bt_list_head
*field_class_declarators
)
1408 struct ctf_node
*iter
;
1409 struct ctf_field_class
*field_decl
= NULL
;
1411 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1414 const char *field_name
;
1416 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1419 BT_ASSERT(!field_decl
);
1420 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1421 "Cannot visit field class declarator: ret=%d", ret
);
1425 BT_ASSERT(field_decl
);
1426 field_name
= g_quark_to_string(qfield_name
);
1428 /* Check if field with same name already exists */
1429 if (ctf_field_class_variant_borrow_option_by_name(variant_decl
, field_name
)) {
1430 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1431 "Duplicate field in variant field class: "
1432 "field-name=\"%s\"",
1438 /* Add field to structure */
1439 ctf_field_class_variant_append_option(variant_decl
, field_name
, field_decl
);
1446 ctf_field_class_destroy(field_decl
);
1451 static int visit_field_class_def(struct ctf_visitor_generate_ir
*ctx
,
1452 struct ctf_node
*cls_specifier_list
,
1453 struct bt_list_head
*field_class_declarators
)
1457 struct ctf_node
*iter
;
1458 struct ctf_field_class
*class_decl
= NULL
;
1460 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1461 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qidentifier
, iter
, &class_decl
,
1464 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit field class declarator: ret=%d",
1470 /* Do not allow field class def and alias of untagged variants */
1471 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1472 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1474 if (var_fc
->tag_path
.path
->len
== 0) {
1475 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1476 iter
, "Type definition of untagged variant field class is not allowed.");
1482 ret
= ctx_decl_scope_register_alias(ctx
, ctx
->current_scope
, g_quark_to_string(qidentifier
),
1485 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot register field class alias: name=\"%s\"",
1486 g_quark_to_string(qidentifier
));
1492 ctf_field_class_destroy(class_decl
);
1497 static int visit_field_class_alias(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*target
,
1498 struct ctf_node
*alias
)
1502 struct ctf_node
*node
;
1503 GQuark qdummy_field_name
;
1504 struct ctf_field_class
*class_decl
= NULL
;
1506 /* Create target field class */
1507 if (bt_list_empty(&target
->u
.field_class_alias_target
.field_class_declarators
)) {
1510 node
= _BT_LIST_FIRST_ENTRY(&target
->u
.field_class_alias_target
.field_class_declarators
,
1511 struct ctf_node
, siblings
);
1514 ret
= visit_field_class_declarator(
1515 ctx
, target
->u
.field_class_alias_target
.field_class_specifier_list
, &qdummy_field_name
,
1516 node
, &class_decl
, NULL
);
1518 BT_ASSERT(!class_decl
);
1519 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot visit field class declarator: ret=%d", ret
);
1523 /* Do not allow field class def and alias of untagged variants */
1524 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1525 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1527 if (var_fc
->tag_path
.path
->len
== 0) {
1528 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1529 target
, "Type definition of untagged variant field class is not allowed.");
1536 * The semantic validator does not check whether the target is
1537 * abstract or not (if it has an identifier). Check it here.
1539 if (qdummy_field_name
!= 0) {
1540 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target
, "Expecting empty identifier: id=\"%s\"",
1541 g_quark_to_string(qdummy_field_name
));
1546 /* Create alias identifier */
1547 node
= _BT_LIST_FIRST_ENTRY(&alias
->u
.field_class_alias_name
.field_class_declarators
,
1548 struct ctf_node
, siblings
);
1549 qalias
= create_class_alias_identifier(
1550 ctx
, alias
->u
.field_class_alias_name
.field_class_specifier_list
, node
);
1551 ret
= ctx_decl_scope_register_alias(ctx
, ctx
->current_scope
, g_quark_to_string(qalias
),
1554 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot register class alias: name=\"%s\"",
1555 g_quark_to_string(qalias
));
1560 ctf_field_class_destroy(class_decl
);
1565 static int visit_struct_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
1566 struct ctf_field_class_struct
*struct_decl
)
1570 switch (entry_node
->type
) {
1572 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1573 &entry_node
->u
.field_class_def
.field_class_declarators
);
1575 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1576 entry_node
, "Cannot add field class found in structure field class: ret=%d", ret
);
1580 case NODE_TYPEALIAS
:
1581 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1582 entry_node
->u
.field_class_alias
.alias
);
1584 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1585 entry_node
, "Cannot add field class alias found in structure field class: ret=%d",
1590 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1592 ret
= visit_struct_decl_field(
1594 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1595 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1601 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
1611 static int visit_variant_decl_entry(struct ctf_visitor_generate_ir
*ctx
,
1612 struct ctf_node
*entry_node
,
1613 struct ctf_field_class_variant
*variant_decl
)
1617 switch (entry_node
->type
) {
1619 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1620 &entry_node
->u
.field_class_def
.field_class_declarators
);
1622 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1623 entry_node
, "Cannot add field class found in variant field class: ret=%d", ret
);
1627 case NODE_TYPEALIAS
:
1628 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1629 entry_node
->u
.field_class_alias
.alias
);
1631 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1632 entry_node
, "Cannot add field class alias found in variant field class: ret=%d",
1637 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1639 ret
= visit_variant_decl_field(
1641 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1642 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1648 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
1658 static int visit_struct_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1659 struct bt_list_head
*decl_list
, int has_body
,
1660 struct bt_list_head
*min_align
,
1661 struct ctf_field_class_struct
**struct_decl
)
1665 BT_ASSERT(struct_decl
);
1666 *struct_decl
= NULL
;
1668 /* For named struct (without body), lookup in declaration scope */
1671 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1672 "Bodyless structure field class: missing name.");
1677 *struct_decl
= ctx_decl_scope_lookup_struct(ctx
, ctx
->current_scope
, name
, -1, true);
1678 if (!*struct_decl
) {
1679 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1680 "Cannot find structure field class: name=\"struct %s\"", name
);
1685 struct ctf_node
*entry_node
;
1686 uint64_t min_align_value
= 0;
1689 if (ctx_decl_scope_lookup_struct(ctx
, ctx
->current_scope
, name
, 1, false)) {
1690 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1691 "Structure field class already declared in local scope: "
1692 "name=\"struct %s\"",
1699 if (!bt_list_empty(min_align
)) {
1700 ret
= get_unary_unsigned(ctx
, min_align
, &min_align_value
);
1702 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1703 "Unexpected unary expression for structure field class's `align` attribute: "
1710 *struct_decl
= ctf_field_class_struct_create();
1711 BT_ASSERT(*struct_decl
);
1713 if (min_align_value
!= 0) {
1714 (*struct_decl
)->base
.alignment
= min_align_value
;
1717 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1719 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1720 ret
= visit_struct_decl_entry(ctx
, entry_node
, *struct_decl
);
1722 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1723 "Cannot visit structure field class entry: "
1734 ret
= ctx_decl_scope_register_struct(ctx
, ctx
->current_scope
, name
, *struct_decl
);
1736 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1737 "Cannot register structure field class in declaration scope: "
1738 "name=\"struct %s\", ret=%d",
1748 ctf_field_class_destroy(&(*struct_decl
)->base
);
1749 *struct_decl
= NULL
;
1753 static int visit_variant_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1754 const char *tag
, struct bt_list_head
*decl_list
, int has_body
,
1755 struct ctf_field_class_variant
**variant_decl
)
1758 struct ctf_field_class_variant
*untagged_variant_decl
= NULL
;
1760 BT_ASSERT(variant_decl
);
1761 *variant_decl
= NULL
;
1763 /* For named variant (without body), lookup in declaration scope */
1766 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name.");
1771 untagged_variant_decl
=
1772 ctx_decl_scope_lookup_variant(ctx
, ctx
->current_scope
, name
, -1, true);
1773 if (!untagged_variant_decl
) {
1774 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1775 "Cannot find variant field class: name=\"variant %s\"", name
);
1780 struct ctf_node
*entry_node
;
1783 if (ctx_decl_scope_lookup_variant(ctx
, ctx
->current_scope
, name
, 1, false)) {
1784 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1785 "Variant field class already declared in local scope: "
1786 "name=\"variant %s\"",
1793 untagged_variant_decl
= ctf_field_class_variant_create();
1794 BT_ASSERT(untagged_variant_decl
);
1795 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1797 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1798 ret
= visit_variant_decl_entry(ctx
, entry_node
, untagged_variant_decl
);
1800 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1801 "Cannot visit variant field class entry: "
1812 ret
= ctx_decl_scope_register_variant(ctx
, ctx
->current_scope
, name
,
1813 untagged_variant_decl
);
1815 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1816 "Cannot register variant field class in declaration scope: "
1817 "name=\"variant %s\", ret=%d",
1825 * If tagged, create tagged variant and return; otherwise
1826 * return untagged variant.
1829 *variant_decl
= untagged_variant_decl
;
1830 untagged_variant_decl
= NULL
;
1833 * At this point, we have a fresh untagged variant; nobody
1834 * else owns it. Set its tag now.
1836 g_string_assign(untagged_variant_decl
->tag_ref
, tag
);
1837 *variant_decl
= untagged_variant_decl
;
1838 untagged_variant_decl
= NULL
;
1841 BT_ASSERT(!untagged_variant_decl
);
1842 BT_ASSERT(*variant_decl
);
1846 ctf_field_class_destroy(&untagged_variant_decl
->base
);
1847 untagged_variant_decl
= NULL
;
1848 ctf_field_class_destroy(&(*variant_decl
)->base
);
1849 *variant_decl
= NULL
;
1863 static int visit_enum_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*enumerator
,
1864 struct ctf_field_class_enum
*enum_decl
, struct uori
*last
)
1868 struct ctf_node
*iter
;
1869 struct uori start
= {
1883 const char *label
= enumerator
->u
.enumerator
.id
;
1884 struct bt_list_head
*values
= &enumerator
->u
.enumerator
.values
;
1886 bt_list_for_each_entry (iter
, values
, siblings
) {
1887 struct uori
*target
;
1889 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
1890 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1891 "Wrong expression for enumeration field class label: "
1892 "node-type=%d, label=\"%s\"",
1904 switch (iter
->u
.unary_expression
.type
) {
1905 case UNARY_SIGNED_CONSTANT
:
1906 target
->is_signed
= true;
1907 target
->value
.i
= iter
->u
.unary_expression
.u
.signed_constant
;
1909 case UNARY_UNSIGNED_CONSTANT
:
1910 target
->is_signed
= false;
1911 target
->value
.u
= iter
->u
.unary_expression
.u
.unsigned_constant
;
1914 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1915 "Invalid enumeration field class entry: "
1916 "expecting constant signed or unsigned integer: "
1917 "node-type=%d, label=\"%s\"",
1918 iter
->u
.unary_expression
.type
, label
);
1924 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1925 iter
, "Invalid enumeration field class entry: label=\"%s\"", label
);
1941 if (end
.is_signed
) {
1942 last
->value
.i
= end
.value
.i
+ 1;
1944 last
->value
.u
= end
.value
.u
+ 1;
1947 ctf_field_class_enum_map_range(enum_decl
, label
, start
.value
.u
, end
.value
.u
);
1954 static int visit_enum_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1955 struct ctf_node
*container_cls
, struct bt_list_head
*enumerator_list
,
1956 int has_body
, struct ctf_field_class_enum
**enum_decl
)
1960 struct ctf_field_class_int
*integer_decl
= NULL
;
1962 BT_ASSERT(enum_decl
);
1965 /* For named enum (without body), lookup in declaration scope */
1968 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1969 "Bodyless enumeration field class: missing name.");
1974 *enum_decl
= ctx_decl_scope_lookup_enum(ctx
, ctx
->current_scope
, name
, -1, true);
1976 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: "
1983 struct ctf_node
*iter
;
1984 struct uori last_value
= {
1993 if (ctx_decl_scope_lookup_enum(ctx
, ctx
->current_scope
, name
, 1, false)) {
1994 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1995 "Enumeration field class already declared in local scope: "
2003 if (!container_cls
) {
2004 integer_decl
= ctf_field_class_as_int(
2005 ctx_decl_scope_lookup_alias(ctx
, ctx
->current_scope
, "int", -1, true));
2006 if (!integer_decl
) {
2007 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2008 "Cannot find implicit `int` field class alias for enumeration field class.");
2013 ctf_field_class
*decl
;
2015 ret
= visit_field_class_declarator(ctx
, container_cls
, &qdummy_id
, NULL
, &decl
, NULL
);
2022 integer_decl
= ctf_field_class_as_int(decl
);
2025 BT_ASSERT(integer_decl
);
2027 if (integer_decl
->base
.base
.type
!= CTF_FIELD_CLASS_TYPE_INT
) {
2028 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2029 "Container field class for enumeration field class is not an integer field class: "
2031 integer_decl
->base
.base
.type
);
2036 *enum_decl
= ctf_field_class_enum_create();
2037 BT_ASSERT(*enum_decl
);
2038 (*enum_decl
)->base
.base
.base
.alignment
= integer_decl
->base
.base
.alignment
;
2039 ctf_field_class_int_copy_content(&(*enum_decl
)->base
, integer_decl
);
2040 last_value
.is_signed
= (*enum_decl
)->base
.is_signed
;
2042 bt_list_for_each_entry (iter
, enumerator_list
, siblings
) {
2043 ret
= visit_enum_decl_entry(ctx
, iter
, *enum_decl
, &last_value
);
2045 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
2046 "Cannot visit enumeration field class entry: "
2054 ret
= ctx_decl_scope_register_enum(ctx
, ctx
->current_scope
, name
, *enum_decl
);
2056 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2057 "Cannot register enumeration field class in declaration scope: "
2068 ctf_field_class_destroy(&(*enum_decl
)->base
.base
.base
);
2072 ctf_field_class_destroy(&integer_decl
->base
.base
);
2073 integer_decl
= NULL
;
2077 static int visit_field_class_specifier(struct ctf_visitor_generate_ir
*ctx
,
2078 struct ctf_node
*cls_specifier_list
,
2079 struct ctf_field_class
**decl
)
2082 GString
*str
= NULL
;
2085 str
= g_string_new("");
2086 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
2088 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2089 cls_specifier_list
, "Cannot get field class specifier list's name: ret=%d", ret
);
2093 *decl
= ctx_decl_scope_lookup_alias(ctx
, ctx
->current_scope
, str
->str
, -1, true);
2095 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2096 "Cannot find field class alias: name=\"%s\"", str
->str
);
2104 ctf_field_class_destroy(*decl
);
2109 g_string_free(str
, TRUE
);
2115 static int visit_integer_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2116 struct ctf_field_class_int
**integer_decl
)
2121 struct ctf_node
*expression
;
2122 uint64_t alignment
= 0, size
= 0;
2123 struct ctf_clock_class
*mapped_clock_class
= NULL
;
2124 enum ctf_encoding encoding
= CTF_ENCODING_NONE
;
2125 bt_field_class_integer_preferred_display_base base
=
2126 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2127 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2129 *integer_decl
= NULL
;
2131 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2132 struct ctf_node
*left
, *right
;
2134 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2136 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2138 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2139 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2140 left
->u
.unary_expression
.type
);
2145 if (strcmp(left
->u
.unary_expression
.u
.string
, "signed") == 0) {
2146 if (_IS_SET(&set
, _INTEGER_SIGNED_SET
)) {
2147 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "signed", "integer field class");
2152 signedness
= get_boolean(ctx
, right
);
2153 if (signedness
< 0) {
2154 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2156 "Invalid boolean value for integer field class's `signed` attribute: "
2163 _SET(&set
, _INTEGER_SIGNED_SET
);
2164 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2165 if (_IS_SET(&set
, _INTEGER_BYTE_ORDER_SET
)) {
2166 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order", "integer field class");
2171 byte_order
= get_real_byte_order(ctx
, right
);
2172 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2173 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2175 "Invalid `byte_order` attribute in integer field class: "
2182 _SET(&set
, _INTEGER_BYTE_ORDER_SET
);
2183 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "size") == 0) {
2184 if (_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2185 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "size", "integer field class");
2190 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2191 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2192 "Invalid `size` attribute in integer field class: "
2193 "expecting unsigned constant integer: "
2195 right
->u
.unary_expression
.type
);
2200 size
= right
->u
.unary_expression
.u
.unsigned_constant
;
2202 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2203 "Invalid `size` attribute in integer field class: "
2204 "expecting positive constant integer: "
2209 } else if (size
> 64) {
2210 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2212 "Invalid `size` attribute in integer field class: "
2213 "integer fields over 64 bits are not supported as of this version: "
2220 _SET(&set
, _INTEGER_SIZE_SET
);
2221 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2222 if (_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2223 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align", "integer field class");
2228 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2229 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2230 "Invalid `align` attribute in integer field class: "
2231 "expecting unsigned constant integer: "
2233 right
->u
.unary_expression
.type
);
2238 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2239 if (!is_align_valid(alignment
)) {
2240 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2241 "Invalid `align` attribute in integer field class: "
2242 "expecting power of two: "
2249 _SET(&set
, _INTEGER_ALIGN_SET
);
2250 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "base") == 0) {
2251 if (_IS_SET(&set
, _INTEGER_BASE_SET
)) {
2252 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "base", "integer field class");
2257 switch (right
->u
.unary_expression
.type
) {
2258 case UNARY_UNSIGNED_CONSTANT
:
2260 uint64_t constant
= right
->u
.unary_expression
.u
.unsigned_constant
;
2264 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2267 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2270 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2273 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2276 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2278 "Invalid `base` attribute in integer field class: "
2280 right
->u
.unary_expression
.u
.unsigned_constant
);
2289 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2291 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2293 "Unexpected unary expression for integer field class's `base` attribute.");
2298 if (strcmp(s_right
, "decimal") == 0 || strcmp(s_right
, "dec") == 0 ||
2299 strcmp(s_right
, "d") == 0 || strcmp(s_right
, "i") == 0 ||
2300 strcmp(s_right
, "u") == 0) {
2301 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2302 } else if (strcmp(s_right
, "hexadecimal") == 0 || strcmp(s_right
, "hex") == 0 ||
2303 strcmp(s_right
, "x") == 0 || strcmp(s_right
, "X") == 0 ||
2304 strcmp(s_right
, "p") == 0) {
2305 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2306 } else if (strcmp(s_right
, "octal") == 0 || strcmp(s_right
, "oct") == 0 ||
2307 strcmp(s_right
, "o") == 0) {
2308 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2309 } else if (strcmp(s_right
, "binary") == 0 || strcmp(s_right
, "b") == 0) {
2310 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2312 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2314 "Unexpected unary expression for integer field class's `base` attribute: "
2326 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2327 right
, "Invalid `base` attribute in integer field class: "
2328 "expecting unsigned constant integer or unary string.");
2333 _SET(&set
, _INTEGER_BASE_SET
);
2334 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2337 if (_IS_SET(&set
, _INTEGER_ENCODING_SET
)) {
2338 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "integer field class");
2343 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2344 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2345 right
, "Invalid `encoding` attribute in integer field class: "
2346 "expecting unary string.");
2351 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2353 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2355 "Unexpected unary expression for integer field class's `encoding` attribute.");
2360 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2361 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2362 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2363 encoding
= CTF_ENCODING_UTF8
;
2364 } else if (strcmp(s_right
, "none") == 0) {
2365 encoding
= CTF_ENCODING_NONE
;
2367 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2369 "Invalid `encoding` attribute in integer field class: "
2370 "unknown encoding: encoding=\"%s\"",
2378 _SET(&set
, _INTEGER_ENCODING_SET
);
2379 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "map") == 0) {
2380 const char *clock_name
;
2382 if (_IS_SET(&set
, _INTEGER_MAP_SET
)) {
2383 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "map", "integer field class");
2388 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2389 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2390 "Invalid `map` attribute in integer field class: "
2391 "expecting unary string.");
2396 clock_name
= get_map_clock_name_value(&expression
->u
.ctf_expression
.right
);
2399 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2402 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2404 "Unexpected unary expression for integer field class's `map` attribute.");
2409 _BT_COMP_LOGE_NODE(right
,
2410 "Invalid `map` attribute in integer field class: "
2411 "cannot find clock class at this point: name=\"%s\"",
2413 _SET(&set
, _INTEGER_MAP_SET
);
2418 mapped_clock_class
=
2419 ctf_trace_class_borrow_clock_class_by_name(ctx
->ctf_tc
, clock_name
);
2420 if (!mapped_clock_class
) {
2421 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2423 "Invalid `map` attribute in integer field class: "
2424 "cannot find clock class at this point: name=\"%s\"",
2430 _SET(&set
, _INTEGER_MAP_SET
);
2432 _BT_COMP_LOGW_NODE(left
,
2433 "Unknown attribute in integer field class: "
2435 left
->u
.unary_expression
.u
.string
);
2439 if (!_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2440 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2441 "Missing `size` attribute in integer field class.");
2446 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2447 if (size
% CHAR_BIT
) {
2448 /* Bit-packed alignment */
2451 /* Byte-packed alignment */
2452 alignment
= CHAR_BIT
;
2456 *integer_decl
= ctf_field_class_int_create();
2457 BT_ASSERT(*integer_decl
);
2458 (*integer_decl
)->base
.base
.alignment
= alignment
;
2459 (*integer_decl
)->base
.byte_order
= byte_order
;
2460 (*integer_decl
)->base
.size
= size
;
2461 (*integer_decl
)->is_signed
= (signedness
> 0);
2462 (*integer_decl
)->disp_base
= base
;
2463 (*integer_decl
)->encoding
= encoding
;
2464 (*integer_decl
)->mapped_clock_class
= mapped_clock_class
;
2468 ctf_field_class_destroy(&(*integer_decl
)->base
.base
);
2469 *integer_decl
= NULL
;
2473 static int visit_floating_point_number_decl(struct ctf_visitor_generate_ir
*ctx
,
2474 struct bt_list_head
*expressions
,
2475 struct ctf_field_class_float
**float_decl
)
2479 struct ctf_node
*expression
;
2480 uint64_t alignment
= 1, exp_dig
= 0, mant_dig
= 0;
2481 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2485 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2486 struct ctf_node
*left
, *right
;
2488 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2490 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2492 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2493 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2494 left
->u
.unary_expression
.type
);
2499 if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2500 if (_IS_SET(&set
, _FLOAT_BYTE_ORDER_SET
)) {
2501 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order",
2502 "floating point number field class");
2507 byte_order
= get_real_byte_order(ctx
, right
);
2508 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2509 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2511 "Invalid `byte_order` attribute in floating point number field class: "
2518 _SET(&set
, _FLOAT_BYTE_ORDER_SET
);
2519 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "exp_dig") == 0) {
2520 if (_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2521 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "exp_dig",
2522 "floating point number field class");
2527 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2528 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2530 "Invalid `exp_dig` attribute in floating point number field class: "
2531 "expecting unsigned constant integer: "
2533 right
->u
.unary_expression
.type
);
2538 exp_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2539 _SET(&set
, _FLOAT_EXP_DIG_SET
);
2540 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "mant_dig") == 0) {
2541 if (_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2542 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "mant_dig",
2543 "floating point number field class");
2548 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2549 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2551 "Invalid `mant_dig` attribute in floating point number field class: "
2552 "expecting unsigned constant integer: "
2554 right
->u
.unary_expression
.type
);
2559 mant_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2560 _SET(&set
, _FLOAT_MANT_DIG_SET
);
2561 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2562 if (_IS_SET(&set
, _FLOAT_ALIGN_SET
)) {
2563 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align",
2564 "floating point number field class");
2569 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2570 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2572 "Invalid `align` attribute in floating point number field class: "
2573 "expecting unsigned constant integer: "
2575 right
->u
.unary_expression
.type
);
2580 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2582 if (!is_align_valid(alignment
)) {
2583 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2585 "Invalid `align` attribute in floating point number field class: "
2586 "expecting power of two: "
2593 _SET(&set
, _FLOAT_ALIGN_SET
);
2595 _BT_COMP_LOGW_NODE(left
,
2596 "Unknown attribute in floating point number field class: "
2598 left
->u
.unary_expression
.u
.string
);
2602 if (!_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2603 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2604 "Missing `mant_dig` attribute in floating point number field class.");
2609 if (!_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2610 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2611 "Missing `exp_dig` attribute in floating point number field class.");
2616 if (mant_dig
!= 24 && mant_dig
!= 53) {
2617 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53.");
2622 if (mant_dig
== 24 && exp_dig
!= 8) {
2623 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2624 "`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2629 if (mant_dig
== 53 && exp_dig
!= 11) {
2630 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2631 "`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2636 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2637 if ((mant_dig
+ exp_dig
) % CHAR_BIT
) {
2638 /* Bit-packed alignment */
2641 /* Byte-packed alignment */
2642 alignment
= CHAR_BIT
;
2646 *float_decl
= ctf_field_class_float_create();
2647 BT_ASSERT(*float_decl
);
2648 (*float_decl
)->base
.base
.alignment
= alignment
;
2649 (*float_decl
)->base
.byte_order
= byte_order
;
2650 (*float_decl
)->base
.size
= mant_dig
+ exp_dig
;
2654 ctf_field_class_destroy(&(*float_decl
)->base
.base
);
2659 static int visit_string_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2660 struct ctf_field_class_string
**string_decl
)
2664 struct ctf_node
*expression
;
2665 enum ctf_encoding encoding
= CTF_ENCODING_UTF8
;
2667 *string_decl
= NULL
;
2669 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2670 struct ctf_node
*left
, *right
;
2672 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2674 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2676 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2677 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2678 left
->u
.unary_expression
.type
);
2683 if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2686 if (_IS_SET(&set
, _STRING_ENCODING_SET
)) {
2687 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "string field class");
2692 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2693 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2694 right
, "Invalid `encoding` attribute in string field class: "
2695 "expecting unary string.");
2700 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2702 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2704 "Unexpected unary expression for string field class's `encoding` attribute.");
2709 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2710 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2711 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2712 encoding
= CTF_ENCODING_UTF8
;
2713 } else if (strcmp(s_right
, "none") == 0) {
2714 encoding
= CTF_ENCODING_NONE
;
2716 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2718 "Invalid `encoding` attribute in string field class: "
2719 "unknown encoding: encoding=\"%s\"",
2727 _SET(&set
, _STRING_ENCODING_SET
);
2729 _BT_COMP_LOGW_NODE(left
,
2730 "Unknown attribute in string field class: "
2732 left
->u
.unary_expression
.u
.string
);
2736 *string_decl
= ctf_field_class_string_create();
2737 BT_ASSERT(*string_decl
);
2738 (*string_decl
)->encoding
= encoding
;
2742 ctf_field_class_destroy(&(*string_decl
)->base
);
2743 *string_decl
= NULL
;
2747 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
2748 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
)
2751 struct ctf_node
*first
, *node
;
2755 if (ts_list
->type
!= NODE_TYPE_SPECIFIER_LIST
) {
2756 _BT_COMP_LOGE_APPEND_CAUSE_NODE(ts_list
, "Unexpected node type: node-type=%d",
2762 first
= _BT_LIST_FIRST_ENTRY(&ts_list
->u
.field_class_specifier_list
.head
, struct ctf_node
,
2764 if (first
->type
!= NODE_TYPE_SPECIFIER
) {
2765 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type=%d", first
->type
);
2770 node
= first
->u
.field_class_specifier
.node
;
2772 switch (first
->u
.field_class_specifier
.type
) {
2773 case TYPESPEC_INTEGER
:
2775 ctf_field_class_int
*int_decl
;
2777 ret
= visit_integer_decl(ctx
, &node
->u
.integer
.expressions
, &int_decl
);
2779 BT_ASSERT(!int_decl
);
2783 *decl
= &int_decl
->base
.base
;
2786 case TYPESPEC_FLOATING_POINT
:
2788 ctf_field_class_float
*float_decl
;
2791 visit_floating_point_number_decl(ctx
, &node
->u
.floating_point
.expressions
, &float_decl
);
2793 BT_ASSERT(!float_decl
);
2797 *decl
= &float_decl
->base
.base
;
2800 case TYPESPEC_STRING
:
2802 ctf_field_class_string
*string_decl
;
2804 ret
= visit_string_decl(ctx
, &node
->u
.string
.expressions
, &string_decl
);
2806 BT_ASSERT(!string_decl
);
2810 *decl
= &string_decl
->base
;
2813 case TYPESPEC_STRUCT
:
2815 ctf_field_class_struct
*struct_decl
;
2817 ret
= visit_struct_decl(ctx
, node
->u
._struct
.name
, &node
->u
._struct
.declaration_list
,
2818 node
->u
._struct
.has_body
, &node
->u
._struct
.min_align
, &struct_decl
);
2820 BT_ASSERT(!struct_decl
);
2824 *decl
= &struct_decl
->base
;
2827 case TYPESPEC_VARIANT
:
2829 ctf_field_class_variant
*variant_decl
;
2831 ret
= visit_variant_decl(ctx
, node
->u
.variant
.name
, node
->u
.variant
.choice
,
2832 &node
->u
.variant
.declaration_list
, node
->u
.variant
.has_body
,
2835 BT_ASSERT(!variant_decl
);
2839 *decl
= &variant_decl
->base
;
2844 ctf_field_class_enum
*enum_decl
;
2846 ret
= visit_enum_decl(ctx
, node
->u
._enum
.enum_id
, node
->u
._enum
.container_field_class
,
2847 &node
->u
._enum
.enumerator_list
, node
->u
._enum
.has_body
, &enum_decl
);
2849 BT_ASSERT(!enum_decl
);
2853 *decl
= &enum_decl
->base
.base
.base
;
2858 case TYPESPEC_SHORT
:
2861 case TYPESPEC_FLOAT
:
2862 case TYPESPEC_DOUBLE
:
2863 case TYPESPEC_SIGNED
:
2864 case TYPESPEC_UNSIGNED
:
2866 case TYPESPEC_COMPLEX
:
2867 case TYPESPEC_IMAGINARY
:
2868 case TYPESPEC_CONST
:
2869 case TYPESPEC_ID_TYPE
:
2870 ret
= visit_field_class_specifier(ctx
, ts_list
, decl
);
2872 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Cannot visit field class specifier: ret=%d",
2879 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
,
2880 "Unexpected field class specifier type: node-type=%d",
2881 first
->u
.field_class_specifier
.type
);
2890 ctf_field_class_destroy(*decl
);
2895 static int visit_event_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
2896 struct ctf_event_class
*event_class
, uint64_t *stream_id
,
2902 switch (node
->type
) {
2904 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
2905 &node
->u
.field_class_def
.field_class_declarators
);
2907 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in event class.");
2911 case NODE_TYPEALIAS
:
2912 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
2913 node
->u
.field_class_alias
.alias
);
2915 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2916 "Cannot add field class alias found in event class.");
2920 case NODE_CTF_EXPRESSION
:
2922 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
2924 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
2929 if (strcmp(left
, "name") == 0) {
2930 /* This is already known at this stage */
2931 if (_IS_SET(set
, _EVENT_NAME_SET
)) {
2932 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "name", "event class");
2937 _SET(set
, _EVENT_NAME_SET
);
2938 } else if (strcmp(left
, "id") == 0) {
2941 if (_IS_SET(set
, _EVENT_ID_SET
)) {
2942 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "event class");
2947 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
2948 /* Only read "id" if get_unary_unsigned() succeeded. */
2949 if (ret
|| (!ret
&& id
< 0)) {
2950 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2951 node
, "Unexpected unary expression for event class's `id` attribute.");
2956 event_class
->id
= id
;
2957 _SET(set
, _EVENT_ID_SET
);
2958 } else if (strcmp(left
, "stream_id") == 0) {
2959 if (_IS_SET(set
, _EVENT_STREAM_ID_SET
)) {
2960 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "stream_id", "event class");
2965 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, stream_id
);
2968 * Only read "stream_id" if get_unary_unsigned()
2972 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2973 node
, "Unexpected unary expression for event class's `stream_id` attribute.");
2978 _SET(set
, _EVENT_STREAM_ID_SET
);
2979 } else if (strcmp(left
, "context") == 0) {
2980 if (_IS_SET(set
, _EVENT_CONTEXT_SET
)) {
2981 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `context` entry in event class.");
2986 ret
= visit_field_class_specifier_list(
2987 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2988 &event_class
->spec_context_fc
);
2990 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2991 "Cannot create event class's context field class.");
2995 BT_ASSERT(event_class
->spec_context_fc
);
2996 _SET(set
, _EVENT_CONTEXT_SET
);
2997 } else if (strcmp(left
, "fields") == 0) {
2998 if (_IS_SET(set
, _EVENT_FIELDS_SET
)) {
2999 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `fields` entry in event class.");
3004 ret
= visit_field_class_specifier_list(
3005 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3006 &event_class
->payload_fc
);
3008 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3009 "Cannot create event class's payload field class.");
3013 BT_ASSERT(event_class
->payload_fc
);
3014 _SET(set
, _EVENT_FIELDS_SET
);
3015 } else if (strcmp(left
, "loglevel") == 0) {
3016 uint64_t loglevel_value
;
3017 bool is_log_level_known
= true;
3018 bt_event_class_log_level log_level
;
3020 if (_IS_SET(set
, _EVENT_LOG_LEVEL_SET
)) {
3021 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "loglevel", "event class");
3026 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &loglevel_value
);
3028 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3029 node
, "Unexpected unary expression for event class's `loglevel` attribute.");
3034 switch (loglevel_value
) {
3036 log_level
= BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
;
3039 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ALERT
;
3042 log_level
= BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
;
3045 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ERROR
;
3048 log_level
= BT_EVENT_CLASS_LOG_LEVEL_WARNING
;
3051 log_level
= BT_EVENT_CLASS_LOG_LEVEL_NOTICE
;
3054 log_level
= BT_EVENT_CLASS_LOG_LEVEL_INFO
;
3057 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
;
3060 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
;
3063 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
;
3066 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
;
3069 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
;
3072 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
;
3075 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
;
3078 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG
;
3081 is_log_level_known
= false;
3084 "Not setting event class's log level because its value is unknown: "
3085 "log-level=%" PRIu64
,
3089 if (is_log_level_known
) {
3090 ctf_event_class_set_log_level(event_class
, log_level
);
3093 _SET(set
, _EVENT_LOG_LEVEL_SET
);
3094 } else if (strcmp(left
, "model.emf.uri") == 0) {
3097 if (_IS_SET(set
, _EVENT_MODEL_EMF_URI_SET
)) {
3098 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "model.emf.uri", "event class");
3103 right
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.right
);
3105 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3107 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3112 if (strlen(right
) == 0) {
3113 _BT_COMP_LOGW_NODE(node
, "Not setting event class's EMF URI because it's empty.");
3115 g_string_assign(event_class
->emf_uri
, right
);
3119 _SET(set
, _EVENT_MODEL_EMF_URI_SET
);
3121 _BT_COMP_LOGW_NODE(node
,
3122 "Unknown attribute in event class: "
3145 static char *get_event_decl_name(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3149 struct ctf_node
*iter
;
3150 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3152 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3153 if (iter
->type
!= NODE_CTF_EXPRESSION
) {
3157 left
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.left
);
3159 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot concatenate unary strings.");
3163 if (strcmp(left
, "name") == 0) {
3164 name
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.right
);
3166 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3167 iter
, "Unexpected unary expression for event class's `name` attribute.");
3187 static int visit_event_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3191 struct ctf_node
*iter
;
3192 uint64_t stream_id
= 0;
3193 char *event_name
= NULL
;
3194 struct ctf_event_class
*event_class
= NULL
;
3195 struct ctf_stream_class
*stream_class
= NULL
;
3196 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3197 bool pop_scope
= false;
3199 if (node
->visited
) {
3203 node
->visited
= TRUE
;
3204 event_name
= get_event_decl_name(ctx
, node
);
3206 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `name` attribute in event class.");
3211 event_class
= ctf_event_class_create();
3212 BT_ASSERT(event_class
);
3213 g_string_assign(event_class
->name
, event_name
);
3214 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3217 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3218 ret
= visit_event_decl_entry(ctx
, iter
, event_class
, &stream_id
, &set
);
3220 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3221 "Cannot visit event class's entry: "
3228 if (!_IS_SET(&set
, _EVENT_STREAM_ID_SET
)) {
3230 * Allow missing stream_id if there is only a single
3233 switch (ctx
->ctf_tc
->stream_classes
->len
) {
3235 /* Create implicit stream class if there's none */
3237 stream_class
= ctf_stream_class_create();
3238 BT_ASSERT(stream_class
);
3239 stream_class
->id
= stream_id
;
3240 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3243 /* Single stream class: get its ID */
3244 stream_class
= (ctf_stream_class
*) ctx
->ctf_tc
->stream_classes
->pdata
[0];
3245 stream_id
= stream_class
->id
;
3248 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `stream_id` attribute in event class.");
3254 /* We have the stream ID now; get the stream class if found */
3255 if (!stream_class
) {
3256 stream_class
= ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_id
);
3257 if (!stream_class
) {
3258 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3259 "Cannot find stream class at this point: "
3267 BT_ASSERT(stream_class
);
3269 if (!_IS_SET(&set
, _EVENT_ID_SET
)) {
3270 /* Allow only one event without ID per stream */
3271 if (stream_class
->event_classes
->len
!= 0) {
3272 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `id` attribute in event class.");
3278 event_class
->id
= 0;
3281 if (ctf_stream_class_borrow_event_class_by_id(stream_class
, event_class
->id
)) {
3282 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3283 "Duplicate event class (same ID) in the same stream class: "
3290 ctf_stream_class_append_event_class(stream_class
, event_class
);
3295 ctf_event_class_destroy(event_class
);
3312 static int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3313 struct ctf_field_class
*fc
)
3315 struct ctf_clock_class
*clock_class_to_map_to
= NULL
;
3316 struct ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
3318 uint64_t clock_class_count
;
3324 if (fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&& fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3328 if (int_fc
->mapped_clock_class
) {
3329 /* Already mapped */
3333 clock_class_count
= ctx
->ctf_tc
->clock_classes
->len
;
3335 switch (clock_class_count
) {
3338 * No clock class exists in the trace at this point. Create an
3339 * implicit one at 1 GHz, named `default`, and use this clock
3342 clock_class_to_map_to
= ctf_clock_class_create();
3343 BT_ASSERT(clock_class_to_map_to
);
3344 clock_class_to_map_to
->frequency
= UINT64_C(1000000000);
3345 g_string_assign(clock_class_to_map_to
->name
, "default");
3346 BT_ASSERT(ret
== 0);
3347 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock_class_to_map_to
);
3351 * Only one clock class exists in the trace at this point: use
3354 clock_class_to_map_to
= (ctf_clock_class
*) ctx
->ctf_tc
->clock_classes
->pdata
[0];
3358 * Timestamp field not mapped to a clock class and there's more
3359 * than one clock class in the trace: this is an error.
3361 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3362 "Timestamp field found with no mapped clock class, "
3363 "but there's more than one clock class in the trace at this point.");
3368 BT_ASSERT(clock_class_to_map_to
);
3369 int_fc
->mapped_clock_class
= clock_class_to_map_to
;
3375 static int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3376 struct ctf_field_class
*root_fc
,
3377 const char *field_name
)
3381 struct ctf_field_class_struct
*struct_fc
= (ctf_field_class_struct
*) root_fc
;
3382 struct ctf_field_class_variant
*var_fc
= (ctf_field_class_variant
*) root_fc
;
3388 if (root_fc
->type
!= CTF_FIELD_CLASS_TYPE_STRUCT
&&
3389 root_fc
->type
!= CTF_FIELD_CLASS_TYPE_VARIANT
) {
3393 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3394 count
= struct_fc
->members
->len
;
3396 count
= var_fc
->options
->len
;
3399 for (i
= 0; i
< count
; i
++) {
3400 struct ctf_named_field_class
*named_fc
= NULL
;
3402 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3403 named_fc
= ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
3404 } else if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
3405 named_fc
= ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
3410 if (strcmp(named_fc
->name
->str
, field_name
) == 0) {
3411 ret
= auto_map_field_to_trace_clock_class(ctx
, named_fc
->fc
);
3413 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3414 "Cannot automatically map field to trace's clock class: "
3415 "field-name=\"%s\"",
3421 ret
= auto_map_fields_to_trace_clock_class(ctx
, named_fc
->fc
, field_name
);
3423 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3424 "Cannot automatically map structure or variant field class's fields to trace's clock class: "
3425 "field-name=\"%s\", root-field-name=\"%s\"",
3426 field_name
, named_fc
->name
->str
);
3435 static int visit_stream_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3436 struct ctf_stream_class
*stream_class
, int *set
)
3441 switch (node
->type
) {
3443 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3444 &node
->u
.field_class_def
.field_class_declarators
);
3446 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in stream class.");
3450 case NODE_TYPEALIAS
:
3451 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3452 node
->u
.field_class_alias
.alias
);
3454 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3455 "Cannot add field class alias found in stream class.");
3459 case NODE_CTF_EXPRESSION
:
3461 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3463 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3468 if (strcmp(left
, "id") == 0) {
3471 if (_IS_SET(set
, _STREAM_ID_SET
)) {
3472 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "stream declaration");
3477 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
3479 /* Only read "id" if get_unary_unsigned() succeeded. */
3480 if (ret
|| (!ret
&& id
< 0)) {
3481 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3482 node
, "Unexpected unary expression for stream class's `id` attribute.");
3487 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, id
)) {
3488 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3489 node
, "Duplicate stream class (same ID): id=%" PRId64
, id
);
3494 stream_class
->id
= id
;
3495 _SET(set
, _STREAM_ID_SET
);
3496 } else if (strcmp(left
, "event.header") == 0) {
3497 if (_IS_SET(set
, _STREAM_EVENT_HEADER_SET
)) {
3498 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3499 "Duplicate `event.header` entry in stream class.");
3504 ret
= visit_field_class_specifier_list(
3505 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3506 &stream_class
->event_header_fc
);
3508 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3509 node
, "Cannot create stream class's event header field class.");
3513 BT_ASSERT(stream_class
->event_header_fc
);
3514 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->event_header_fc
,
3517 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3519 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3523 _SET(set
, _STREAM_EVENT_HEADER_SET
);
3524 } else if (strcmp(left
, "event.context") == 0) {
3525 if (_IS_SET(set
, _STREAM_EVENT_CONTEXT_SET
)) {
3526 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3527 "Duplicate `event.context` entry in stream class.");
3532 ret
= visit_field_class_specifier_list(
3533 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3534 &stream_class
->event_common_context_fc
);
3536 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3537 node
, "Cannot create stream class's event context field class.");
3541 BT_ASSERT(stream_class
->event_common_context_fc
);
3542 _SET(set
, _STREAM_EVENT_CONTEXT_SET
);
3543 } else if (strcmp(left
, "packet.context") == 0) {
3544 if (_IS_SET(set
, _STREAM_PACKET_CONTEXT_SET
)) {
3545 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3546 node
, "Duplicate `packet.context` entry in stream class.");
3551 ret
= visit_field_class_specifier_list(
3552 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3553 &stream_class
->packet_context_fc
);
3555 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3556 node
, "Cannot create stream class's packet context field class.");
3560 BT_ASSERT(stream_class
->packet_context_fc
);
3561 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3564 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3566 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3570 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3573 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3575 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3579 _SET(set
, _STREAM_PACKET_CONTEXT_SET
);
3581 _BT_COMP_LOGW_NODE(node
,
3582 "Unknown attribute in stream class: "
3604 static int visit_stream_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3608 struct ctf_node
*iter
;
3609 struct ctf_stream_class
*stream_class
= NULL
;
3610 struct bt_list_head
*decl_list
= &node
->u
.stream
.declaration_list
;
3612 if (node
->visited
) {
3616 node
->visited
= TRUE
;
3617 stream_class
= ctf_stream_class_create();
3618 BT_ASSERT(stream_class
);
3619 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3621 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3622 ret
= visit_stream_decl_entry(ctx
, iter
, stream_class
, &set
);
3624 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3625 "Cannot visit stream class's entry: "
3635 if (_IS_SET(&set
, _STREAM_ID_SET
)) {
3636 /* Check that packet header has `stream_id` field */
3637 struct ctf_named_field_class
*named_fc
= NULL
;
3639 if (!ctx
->ctf_tc
->packet_header_fc
) {
3640 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Stream class has a `id` attribute, "
3641 "but trace has no packet header field class.");
3646 named_fc
= ctf_field_class_struct_borrow_member_by_name(
3647 ctf_field_class_as_struct(ctx
->ctf_tc
->packet_header_fc
), "stream_id");
3649 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3650 node
, "Stream class has a `id` attribute, "
3651 "but trace's packet header field class has no `stream_id` field.");
3656 if (named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3657 named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3658 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3660 "Stream class has a `id` attribute, "
3661 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3666 /* Allow only _one_ ID-less stream */
3667 if (ctx
->ctf_tc
->stream_classes
->len
!= 0) {
3668 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3670 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3675 /* Automatic ID: 0 */
3676 stream_class
->id
= 0;
3680 * Make sure that this stream class's ID is currently unique in
3683 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_class
->id
)) {
3684 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate stream class (same ID): id=%" PRId64
,
3690 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3691 stream_class
= NULL
;
3695 ctf_stream_class_destroy(stream_class
);
3696 stream_class
= NULL
;
3702 static int visit_trace_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3709 switch (node
->type
) {
3711 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3712 &node
->u
.field_class_def
.field_class_declarators
);
3714 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3715 node
, "Cannot add field class found in trace (`trace` block).");
3719 case NODE_TYPEALIAS
:
3720 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3721 node
->u
.field_class_alias
.alias
);
3723 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3724 node
, "Cannot add field class alias found in trace (`trace` block).");
3728 case NODE_CTF_EXPRESSION
:
3730 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3732 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3737 if (strcmp(left
, "major") == 0) {
3738 if (_IS_SET(set
, _TRACE_MAJOR_SET
)) {
3739 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "major", "trace");
3744 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3746 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3747 node
, "Unexpected unary expression for trace's `major` attribute.");
3753 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3754 "Invalid trace's `minor` attribute: expecting 1.");
3759 ctx
->ctf_tc
->major
= val
;
3760 _SET(set
, _TRACE_MAJOR_SET
);
3761 } else if (strcmp(left
, "minor") == 0) {
3762 if (_IS_SET(set
, _TRACE_MINOR_SET
)) {
3763 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "minor", "trace");
3768 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3770 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3771 node
, "Unexpected unary expression for trace's `minor` attribute.");
3777 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3778 "Invalid trace's `minor` attribute: expecting 8.");
3783 ctx
->ctf_tc
->minor
= val
;
3784 _SET(set
, _TRACE_MINOR_SET
);
3785 } else if (strcmp(left
, "uuid") == 0) {
3786 if (_IS_SET(set
, _TRACE_UUID_SET
)) {
3787 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "uuid", "trace");
3792 ret
= get_unary_uuid(ctx
, &node
->u
.ctf_expression
.right
, ctx
->ctf_tc
->uuid
);
3794 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid trace's `uuid` attribute.");
3798 ctx
->ctf_tc
->is_uuid_set
= true;
3799 _SET(set
, _TRACE_UUID_SET
);
3800 } else if (strcmp(left
, "byte_order") == 0) {
3801 /* Default byte order is already known at this stage */
3802 if (_IS_SET(set
, _TRACE_BYTE_ORDER_SET
)) {
3803 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
3808 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
!= CTF_BYTE_ORDER_UNKNOWN
);
3809 _SET(set
, _TRACE_BYTE_ORDER_SET
);
3810 } else if (strcmp(left
, "packet.header") == 0) {
3811 if (_IS_SET(set
, _TRACE_PACKET_HEADER_SET
)) {
3812 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `packet.header` entry in trace.");
3817 ret
= visit_field_class_specifier_list(
3818 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3819 &ctx
->ctf_tc
->packet_header_fc
);
3821 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3822 "Cannot create trace's packet header field class.");
3826 BT_ASSERT(ctx
->ctf_tc
->packet_header_fc
);
3827 _SET(set
, _TRACE_PACKET_HEADER_SET
);
3829 _BT_COMP_LOGW_NODE(node
,
3830 "Unknown attribute in stream class: "
3840 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unknown expression in trace.");
3852 static int visit_trace_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3856 struct ctf_node
*iter
;
3857 struct bt_list_head
*decl_list
= &node
->u
.trace
.declaration_list
;
3859 if (node
->visited
) {
3863 node
->visited
= TRUE
;
3865 if (ctx
->is_trace_visited
) {
3866 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
3871 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3873 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3874 ret
= visit_trace_decl_entry(ctx
, iter
, &set
);
3876 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3877 "Cannot visit trace's entry (`trace` block): "
3887 if (!_IS_SET(&set
, _TRACE_MAJOR_SET
)) {
3888 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3889 "Missing `major` attribute in trace (`trace` block).");
3894 if (!_IS_SET(&set
, _TRACE_MINOR_SET
)) {
3895 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3896 "Missing `minor` attribute in trace (`trace` block).");
3901 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3902 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3903 "Missing `byte_order` attribute in trace (`trace` block).");
3908 ctx
->is_trace_visited
= true;
3917 static int visit_env(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3921 struct ctf_node
*entry_node
;
3922 struct bt_list_head
*decl_list
= &node
->u
.env
.declaration_list
;
3924 if (node
->visited
) {
3928 node
->visited
= TRUE
;
3930 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
3931 struct bt_list_head
*right_head
= &entry_node
->u
.ctf_expression
.right
;
3933 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
3934 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
3935 "Wrong expression in environment entry: "
3942 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
3944 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot get environment entry's name.");
3949 if (is_unary_string(right_head
)) {
3950 char *right
= ctf_ast_concatenate_unary_strings(right_head
);
3953 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3955 "Unexpected unary expression for environment entry's value: "
3962 if (strcmp(left
, "tracer_name") == 0) {
3963 if (strncmp(right
, "lttng", 5) == 0) {
3964 BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: "
3965 "tracer-name=\"%s\"",
3967 ctx
->is_lttng
= true;
3971 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
,
3974 } else if (is_unary_unsigned(right_head
) || is_unary_signed(right_head
)) {
3977 if (is_unary_unsigned(right_head
)) {
3978 ret
= get_unary_unsigned(ctx
, right_head
, (uint64_t *) &v
);
3980 ret
= get_unary_signed(right_head
, &v
);
3983 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3985 "Unexpected unary expression for environment entry's value: "
3992 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
,
3995 _BT_COMP_LOGW_NODE(entry_node
,
3996 "Environment entry has unknown type: "
4013 static int set_trace_byte_order(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*trace_node
)
4018 struct ctf_node
*node
;
4019 struct bt_list_head
*decl_list
= &trace_node
->u
.trace
.declaration_list
;
4021 bt_list_for_each_entry (node
, decl_list
, siblings
) {
4022 if (node
->type
== NODE_CTF_EXPRESSION
) {
4023 struct ctf_node
*right_node
;
4025 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
4027 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
4032 if (strcmp(left
, "byte_order") == 0) {
4033 enum ctf_byte_order bo
;
4035 if (_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4036 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
4041 _SET(&set
, _TRACE_BYTE_ORDER_SET
);
4043 _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4044 bo
= byte_order_from_unary_expr(ctx
, right_node
);
4045 if (bo
== CTF_BYTE_ORDER_UNKNOWN
) {
4046 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4047 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4048 "expecting `le`, `be`, or `network`.");
4051 } else if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
4052 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4053 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4054 "cannot be set to `native` here.");
4059 ctx
->ctf_tc
->default_byte_order
= bo
;
4067 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4068 _BT_COMP_LOGE_APPEND_CAUSE_NODE(trace_node
,
4069 "Missing `byte_order` attribute in trace (`trace` block).");
4081 static int visit_clock_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
4082 struct ctf_clock_class
*clock
, int *set
, int64_t *offset_seconds
,
4083 uint64_t *offset_cycles
)
4088 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4089 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
4095 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
4097 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot concatenate unary strings.");
4102 if (strcmp(left
, "name") == 0) {
4105 if (_IS_SET(set
, _CLOCK_NAME_SET
)) {
4106 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "name", "clock class");
4111 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4113 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4114 entry_node
, "Unexpected unary expression for clock class's `name` attribute.");
4119 g_string_assign(clock
->name
, right
);
4121 _SET(set
, _CLOCK_NAME_SET
);
4122 } else if (strcmp(left
, "uuid") == 0) {
4125 if (_IS_SET(set
, _CLOCK_UUID_SET
)) {
4126 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "uuid", "clock class");
4131 ret
= get_unary_uuid(ctx
, &entry_node
->u
.ctf_expression
.right
, uuid
);
4133 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Invalid clock class's `uuid` attribute.");
4137 clock
->has_uuid
= true;
4138 bt_uuid_copy(clock
->uuid
, uuid
);
4139 _SET(set
, _CLOCK_UUID_SET
);
4140 } else if (strcmp(left
, "description") == 0) {
4143 if (_IS_SET(set
, _CLOCK_DESCRIPTION_SET
)) {
4144 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "description", "clock class");
4149 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4151 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4153 "Unexpected unary expression for clock class's `description` attribute.");
4158 g_string_assign(clock
->description
, right
);
4160 _SET(set
, _CLOCK_DESCRIPTION_SET
);
4161 } else if (strcmp(left
, "freq") == 0) {
4162 uint64_t freq
= UINT64_C(-1);
4164 if (_IS_SET(set
, _CLOCK_FREQ_SET
)) {
4165 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "freq", "clock class");
4170 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &freq
);
4172 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4173 entry_node
, "Unexpected unary expression for clock class's `freq` attribute.");
4178 if (freq
== UINT64_C(-1) || freq
== 0) {
4179 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4180 "Invalid clock class frequency: freq=%" PRIu64
, freq
);
4185 clock
->frequency
= freq
;
4186 _SET(set
, _CLOCK_FREQ_SET
);
4187 } else if (strcmp(left
, "precision") == 0) {
4190 if (_IS_SET(set
, _CLOCK_PRECISION_SET
)) {
4191 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "precision", "clock class");
4196 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &precision
);
4198 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4199 entry_node
, "Unexpected unary expression for clock class's `precision` attribute.");
4204 clock
->precision
= precision
;
4205 _SET(set
, _CLOCK_PRECISION_SET
);
4206 } else if (strcmp(left
, "offset_s") == 0) {
4207 if (_IS_SET(set
, _CLOCK_OFFSET_S_SET
)) {
4208 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset_s", "clock class");
4213 ret
= get_unary_signed(&entry_node
->u
.ctf_expression
.right
, offset_seconds
);
4215 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4216 entry_node
, "Unexpected unary expression for clock class's `offset_s` attribute.");
4221 _SET(set
, _CLOCK_OFFSET_S_SET
);
4222 } else if (strcmp(left
, "offset") == 0) {
4223 if (_IS_SET(set
, _CLOCK_OFFSET_SET
)) {
4224 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset", "clock class");
4229 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, offset_cycles
);
4231 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4232 entry_node
, "Unexpected unary expression for clock class's `offset` attribute.");
4237 _SET(set
, _CLOCK_OFFSET_SET
);
4238 } else if (strcmp(left
, "absolute") == 0) {
4239 struct ctf_node
*right
;
4241 if (_IS_SET(set
, _CLOCK_ABSOLUTE_SET
)) {
4242 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "absolute", "clock class");
4248 _BT_LIST_FIRST_ENTRY(&entry_node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4249 ret
= get_boolean(ctx
, right
);
4251 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4252 entry_node
, "Unexpected unary expression for clock class's `absolute` attribute.");
4257 clock
->is_absolute
= ret
;
4258 _SET(set
, _CLOCK_ABSOLUTE_SET
);
4260 _BT_COMP_LOGW_NODE(entry_node
, "Unknown attribute in clock class: attr-name=\"%s\"", left
);
4272 static inline uint64_t cycles_from_ns(uint64_t frequency
, uint64_t ns
)
4277 if (frequency
== UINT64_C(1000000000)) {
4280 cycles
= (uint64_t) (((double) ns
* (double) frequency
) / 1e9
);
4286 static void calibrate_clock_class_offsets(int64_t *offset_seconds
, uint64_t *offset_cycles
,
4289 if (*offset_cycles
>= freq
) {
4290 const uint64_t s_in_offset_cycles
= *offset_cycles
/ freq
;
4292 *offset_seconds
+= (int64_t) s_in_offset_cycles
;
4293 *offset_cycles
-= (s_in_offset_cycles
* freq
);
4297 static void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir
*ctx
,
4298 struct ctf_clock_class
*clock
)
4300 if (ctx
->decoder_config
.force_clock_class_origin_unix_epoch
) {
4301 clock
->is_absolute
= true;
4307 static void apply_clock_class_offset(struct ctf_visitor_generate_ir
*ctx
,
4308 struct ctf_clock_class
*clock
)
4311 int64_t offset_s_to_apply
= ctx
->decoder_config
.clock_class_offset_s
;
4312 uint64_t offset_ns_to_apply
;
4313 int64_t cur_offset_s
;
4314 uint64_t cur_offset_cycles
;
4316 if (ctx
->decoder_config
.clock_class_offset_s
== 0 &&
4317 ctx
->decoder_config
.clock_class_offset_ns
== 0) {
4321 /* Transfer nanoseconds to seconds as much as possible */
4322 if (ctx
->decoder_config
.clock_class_offset_ns
< 0) {
4323 const int64_t abs_ns
= -ctx
->decoder_config
.clock_class_offset_ns
;
4324 const int64_t abs_extra_s
= abs_ns
/ INT64_C(1000000000) + 1;
4325 const int64_t extra_s
= -abs_extra_s
;
4326 const int64_t offset_ns
=
4327 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4329 BT_ASSERT(offset_ns
> 0);
4330 offset_ns_to_apply
= (uint64_t) offset_ns
;
4331 offset_s_to_apply
+= extra_s
;
4333 const int64_t extra_s
= ctx
->decoder_config
.clock_class_offset_ns
/ INT64_C(1000000000);
4334 const int64_t offset_ns
=
4335 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4337 BT_ASSERT(offset_ns
>= 0);
4338 offset_ns_to_apply
= (uint64_t) offset_ns
;
4339 offset_s_to_apply
+= extra_s
;
4342 freq
= clock
->frequency
;
4343 cur_offset_s
= clock
->offset_seconds
;
4344 cur_offset_cycles
= clock
->offset_cycles
;
4347 cur_offset_s
+= offset_s_to_apply
;
4348 cur_offset_cycles
+= cycles_from_ns(freq
, offset_ns_to_apply
);
4351 * Recalibrate offsets because the part in cycles can be greater
4352 * than the frequency at this point.
4354 calibrate_clock_class_offsets(&cur_offset_s
, &cur_offset_cycles
, freq
);
4356 /* Set final offsets */
4357 clock
->offset_seconds
= cur_offset_s
;
4358 clock
->offset_cycles
= cur_offset_cycles
;
4364 static int visit_clock_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*clock_node
)
4368 struct ctf_clock_class
*clock
;
4369 struct ctf_node
*entry_node
;
4370 struct bt_list_head
*decl_list
= &clock_node
->u
.clock
.declaration_list
;
4371 const char *clock_class_name
;
4372 int64_t offset_seconds
= 0;
4373 uint64_t offset_cycles
= 0;
4376 if (clock_node
->visited
) {
4380 clock_node
->visited
= TRUE
;
4382 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4383 clock
= ctf_clock_class_create();
4385 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
, "Cannot create default clock class.");
4390 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
4391 ret
= visit_clock_decl_entry(ctx
, entry_node
, clock
, &set
, &offset_seconds
, &offset_cycles
);
4393 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot visit clock class's entry: ret=%d",
4399 if (!_IS_SET(&set
, _CLOCK_NAME_SET
)) {
4400 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
, "Missing `name` attribute in clock class.");
4405 clock_class_name
= clock
->name
->str
;
4406 BT_ASSERT(clock_class_name
);
4407 if (ctx
->is_lttng
&& strcmp(clock_class_name
, "monotonic") == 0) {
4409 * Old versions of LTTng forgot to set its clock class
4410 * as absolute, even if it is. This is important because
4411 * it's a condition to be able to sort messages
4412 * from different sources.
4414 clock
->is_absolute
= true;
4418 * Adjust offsets so that the part in cycles is less than the
4419 * frequency (move to the part in seconds).
4421 freq
= clock
->frequency
;
4422 calibrate_clock_class_offsets(&offset_seconds
, &offset_cycles
, freq
);
4423 BT_ASSERT(offset_cycles
< clock
->frequency
);
4424 clock
->offset_seconds
= offset_seconds
;
4425 clock
->offset_cycles
= offset_cycles
;
4426 apply_clock_class_offset(ctx
, clock
);
4427 apply_clock_class_is_absolute(ctx
, clock
);
4428 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock
);
4433 ctf_clock_class_destroy(clock
);
4439 static int visit_root_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*root_decl_node
)
4443 if (root_decl_node
->visited
) {
4447 root_decl_node
->visited
= TRUE
;
4449 switch (root_decl_node
->type
) {
4452 visit_field_class_def(ctx
, root_decl_node
->u
.field_class_def
.field_class_specifier_list
,
4453 &root_decl_node
->u
.field_class_def
.field_class_declarators
);
4455 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4456 "Cannot add field class found in root scope.");
4460 case NODE_TYPEALIAS
:
4461 ret
= visit_field_class_alias(ctx
, root_decl_node
->u
.field_class_alias
.target
,
4462 root_decl_node
->u
.field_class_alias
.alias
);
4464 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4465 "Cannot add field class alias found in root scope.");
4469 case NODE_TYPE_SPECIFIER_LIST
:
4471 struct ctf_field_class
*decl
= NULL
;
4474 * Just add the field class specifier to the root
4475 * declaration scope. Put local reference.
4477 ret
= visit_field_class_specifier_list(ctx
, root_decl_node
, &decl
);
4479 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4480 "Cannot visit root scope's field class: "
4487 ctf_field_class_destroy(decl
);
4492 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
, "Unexpected node type: node-type=%d",
4493 root_decl_node
->type
);
4503 struct ctf_visitor_generate_ir
*
4504 ctf_visitor_generate_ir_create(const struct ctf_metadata_decoder_config
*decoder_config
)
4506 struct ctf_visitor_generate_ir
*ctx
= NULL
;
4508 /* Create visitor's context */
4509 ctx
= ctx_create(decoder_config
);
4511 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
, decoder_config
->self_comp
,
4512 "Cannot create visitor's context.");
4527 void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir
*visitor
)
4529 ctx_destroy(visitor
);
4533 bt_trace_class
*ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4537 if (ctx
->trace_class
) {
4538 bt_trace_class_get_ref(ctx
->trace_class
);
4541 return ctx
->trace_class
;
4545 struct ctf_trace_class
*
4546 ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4549 BT_ASSERT_DBG(ctx
->ctf_tc
);
4554 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
4558 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
4560 switch (node
->type
) {
4563 struct ctf_node
*iter
;
4564 bool got_trace_decl
= false;
4567 * The first thing we need is the native byte order of
4568 * the trace block, because early class aliases can have
4569 * a `byte_order` attribute set to `native`. If we don't
4570 * have the native byte order yet, and we don't have any
4571 * trace block yet, then fail with EINCOMPLETE.
4573 if (ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
4574 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4575 if (got_trace_decl
) {
4576 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
4581 ret
= set_trace_byte_order(ctx
, iter
);
4583 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4584 "Cannot set trace's native byte order: "
4590 got_trace_decl
= true;
4593 if (!got_trace_decl
) {
4594 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
4600 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_LITTLE
||
4601 ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_BIG
);
4602 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4605 bt_list_for_each_entry (iter
, &node
->u
.root
.env
, siblings
) {
4606 ret
= visit_env(ctx
, iter
);
4608 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4610 "Cannot visit trace's environment (`env` block) entry: "
4617 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4620 * Visit clock blocks.
4622 bt_list_for_each_entry (iter
, &node
->u
.root
.clock
, siblings
) {
4623 ret
= visit_clock_decl(ctx
, iter
);
4625 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit clock class: ret=%d", ret
);
4630 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4633 * Visit root declarations next, as they can be used by any
4636 bt_list_for_each_entry (iter
, &node
->u
.root
.declaration_list
, siblings
) {
4637 ret
= visit_root_decl(ctx
, iter
);
4639 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit root entry: ret=%d", ret
);
4644 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4646 /* Callsite blocks are not supported */
4647 bt_list_for_each_entry (iter
, &node
->u
.root
.callsite
, siblings
) {
4648 _BT_COMP_LOGW_NODE(iter
, "\"callsite\" blocks are not supported as of this version.");
4651 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4654 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4655 ret
= visit_trace_decl(ctx
, iter
);
4657 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4658 "Cannot visit trace (`trace` block): "
4665 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4668 bt_list_for_each_entry (iter
, &node
->u
.root
.stream
, siblings
) {
4669 ret
= visit_stream_decl(ctx
, iter
);
4671 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit stream class: ret=%d", ret
);
4676 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4679 bt_list_for_each_entry (iter
, &node
->u
.root
.event
, siblings
) {
4680 ret
= visit_event_decl(ctx
, iter
);
4682 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit event class: ret=%d", ret
);
4687 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4691 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected node type: node-type=%d", node
->type
);
4696 /* Update default clock classes */
4697 ret
= ctf_trace_class_update_default_clock_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4703 /* Update trace class meanings */
4704 ret
= ctf_trace_class_update_meanings(ctx
->ctf_tc
);
4710 /* Update stream class configuration */
4711 ret
= ctf_trace_class_update_stream_class_config(ctx
->ctf_tc
);
4717 /* Update text arrays and sequences */
4718 ret
= ctf_trace_class_update_text_array_sequence(ctx
->ctf_tc
);
4724 /* Update structure/array/sequence alignments */
4725 ret
= ctf_trace_class_update_alignments(ctx
->ctf_tc
);
4731 /* Resolve sequence lengths and variant tags */
4732 ret
= ctf_trace_class_resolve_field_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4738 if (ctx
->trace_class
) {
4740 * Update "in IR" for field classes.
4742 * If we have no IR trace class, then we'll have no way
4743 * to create IR fields anyway, so we leave all the
4744 * `in_ir` members false.
4746 ret
= ctf_trace_class_update_in_ir(ctx
->ctf_tc
);
4753 /* Update saved value indexes */
4754 ret
= ctf_trace_class_update_value_storing_indexes(ctx
->ctf_tc
);
4760 /* Validate what we have so far */
4761 ret
= ctf_trace_class_validate(ctx
->ctf_tc
, &ctx
->log_cfg
);
4768 * If there are fields which are not related to the CTF format
4769 * itself in the packet header and in event header field
4770 * classes, warn about it because they are never translated.
4772 ctf_trace_class_warn_meaningless_header_fields(ctx
->ctf_tc
, &ctx
->log_cfg
);
4774 if (ctx
->trace_class
) {
4775 /* Copy new CTF metadata -> new IR metadata */
4776 ret
= ctf_trace_class_translate(ctx
->log_cfg
.self_comp
, ctx
->trace_class
, ctx
->ctf_tc
);