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 */
59 _CLOCK_NAME_SET
= _BV(0),
60 _CLOCK_UUID_SET
= _BV(1),
61 _CLOCK_FREQ_SET
= _BV(2),
62 _CLOCK_PRECISION_SET
= _BV(3),
63 _CLOCK_OFFSET_S_SET
= _BV(4),
64 _CLOCK_OFFSET_SET
= _BV(5),
65 _CLOCK_ABSOLUTE_SET
= _BV(6),
66 _CLOCK_DESCRIPTION_SET
= _BV(7),
70 _INTEGER_ALIGN_SET
= _BV(0),
71 _INTEGER_SIZE_SET
= _BV(1),
72 _INTEGER_BASE_SET
= _BV(2),
73 _INTEGER_ENCODING_SET
= _BV(3),
74 _INTEGER_BYTE_ORDER_SET
= _BV(4),
75 _INTEGER_SIGNED_SET
= _BV(5),
76 _INTEGER_MAP_SET
= _BV(6),
80 _FLOAT_ALIGN_SET
= _BV(0),
81 _FLOAT_MANT_DIG_SET
= _BV(1),
82 _FLOAT_EXP_DIG_SET
= _BV(2),
83 _FLOAT_BYTE_ORDER_SET
= _BV(3),
87 _STRING_ENCODING_SET
= _BV(0),
91 _TRACE_MINOR_SET
= _BV(0),
92 _TRACE_MAJOR_SET
= _BV(1),
93 _TRACE_BYTE_ORDER_SET
= _BV(2),
94 _TRACE_UUID_SET
= _BV(3),
95 _TRACE_PACKET_HEADER_SET
= _BV(4),
99 _STREAM_ID_SET
= _BV(0),
100 _STREAM_PACKET_CONTEXT_SET
= _BV(1),
101 _STREAM_EVENT_HEADER_SET
= _BV(2),
102 _STREAM_EVENT_CONTEXT_SET
= _BV(3),
106 _EVENT_NAME_SET
= _BV(0),
107 _EVENT_ID_SET
= _BV(1),
108 _EVENT_MODEL_EMF_URI_SET
= _BV(2),
109 _EVENT_STREAM_ID_SET
= _BV(3),
110 _EVENT_LOG_LEVEL_SET
= _BV(4),
111 _EVENT_CONTEXT_SET
= _BV(5),
112 _EVENT_FIELDS_SET
= _BV(6),
120 LOG_LEVEL_WARNING
= 4,
121 LOG_LEVEL_NOTICE
= 5,
123 LOG_LEVEL_DEBUG_SYSTEM
= 7,
124 LOG_LEVEL_DEBUG_PROGRAM
= 8,
125 LOG_LEVEL_DEBUG_PROCESS
= 9,
126 LOG_LEVEL_DEBUG_MODULE
= 10,
127 LOG_LEVEL_DEBUG_UNIT
= 11,
128 LOG_LEVEL_DEBUG_FUNCTION
= 12,
129 LOG_LEVEL_DEBUG_LINE
= 13,
130 LOG_LEVEL_DEBUG
= 14,
134 /* Prefixes of class aliases */
135 #define _PREFIX_ALIAS 'a'
136 #define _PREFIX_ENUM 'e'
137 #define _PREFIX_STRUCT 's'
138 #define _PREFIX_VARIANT 'v'
140 /* First entry in a BT list */
141 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) \
142 bt_list_entry((_ptr)->next, _class, _member)
144 #define _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \
145 _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, \
146 "Duplicate attribute in %s: attr-name=\"%s\"", \
149 #define _BT_COMP_LOGE_NODE(_node, _msg, args...) \
150 _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ## args)
152 #define _BT_COMP_LOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
153 _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, _msg, ## args)
155 #define _BT_COMP_LOGW_NODE(_node, _msg, args...) \
156 _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ## args)
158 #define _BT_COMP_LOGT_NODE(_node, _msg, args...) \
159 _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ## args)
162 * Declaration scope of a visitor context. This represents a TSDL
163 * lexical scope, so that aliases and named structures, variants,
164 * and enumerations may be registered and looked up hierarchically.
166 struct ctx_decl_scope
{
168 * Alias name to field class.
170 * GQuark -> struct ctf_field_class * (owned by this)
172 GHashTable
*decl_map
;
174 /* Parent scope; NULL if this is the root declaration scope */
175 struct ctx_decl_scope
*parent_scope
;
179 * Visitor context (private).
181 struct ctf_visitor_generate_ir
{
182 struct meta_log_config log_cfg
;
184 /* Trace IR trace class being filled (owned by this) */
185 bt_trace_class
*trace_class
;
187 /* CTF meta trace being filled (owned by this) */
188 struct ctf_trace_class
*ctf_tc
;
190 /* Current declaration scope (top of the stack) (owned by this) */
191 struct ctx_decl_scope
*current_scope
;
193 /* True if trace declaration is visited */
194 bool is_trace_visited
;
196 /* True if this is an LTTng trace */
199 /* Config passed by the user */
200 struct ctf_metadata_decoder_config decoder_config
;
206 struct ctf_visitor_generate_ir
;
209 * Creates a new declaration scope.
211 * @param par_scope Parent scope (NULL if creating a root scope)
212 * @returns New declaration scope, or NULL on error
215 struct ctx_decl_scope
*ctx_decl_scope_create(struct ctf_visitor_generate_ir
*ctx
,
216 struct ctx_decl_scope
*par_scope
)
218 struct ctx_decl_scope
*scope
;
220 scope
= g_new(struct ctx_decl_scope
, 1);
222 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate one declaration scope.");
226 scope
->decl_map
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
,
227 NULL
, (GDestroyNotify
) ctf_field_class_destroy
);
228 scope
->parent_scope
= par_scope
;
235 * Destroys a declaration scope.
237 * This function does not destroy the parent scope.
239 * @param scope Scope to destroy
242 void ctx_decl_scope_destroy(struct ctx_decl_scope
*scope
)
248 g_hash_table_destroy(scope
->decl_map
);
256 * Returns the GQuark of a prefixed alias.
258 * @param prefix Prefix character
260 * @returns Associated GQuark, or 0 on error
263 GQuark
get_prefixed_named_quark(struct ctf_visitor_generate_ir
*ctx
, char prefix
,
270 /* Prefix character + original string + '\0' */
271 char *prname
= g_new(char, strlen(name
) + 2);
273 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate a string.");
277 sprintf(prname
, "%c%s", prefix
, name
);
278 qname
= g_quark_from_string(prname
);
286 * Looks up a prefixed class alias within a declaration scope.
288 * @param scope Declaration scope
289 * @param prefix Prefix character
290 * @param name Alias name
291 * @param levels Number of levels to dig into (-1 means infinite)
292 * @param copy True to return a copy
293 * @returns Declaration (owned by caller if \p copy is true),
294 * or NULL if not found
297 struct ctf_field_class
*ctx_decl_scope_lookup_prefix_alias(
298 struct ctf_visitor_generate_ir
*ctx
, struct ctx_decl_scope
*scope
, char prefix
,
299 const char *name
, int levels
, bool copy
)
303 struct ctf_field_class
*decl
= NULL
;
304 struct ctx_decl_scope
*cur_scope
= scope
;
308 qname
= get_prefixed_named_quark(ctx
, prefix
, name
);
317 while (cur_scope
&& cur_levels
< levels
) {
318 decl
= (ctf_field_class
*) g_hash_table_lookup(cur_scope
->decl_map
,
319 (gconstpointer
) GUINT_TO_POINTER(qname
));
321 /* Caller's reference */
323 decl
= ctf_field_class_copy(decl
);
330 cur_scope
= cur_scope
->parent_scope
;
339 * Looks up a class alias within a declaration scope.
341 * @param scope Declaration scope
342 * @param name Alias name
343 * @param levels Number of levels to dig into (-1 means infinite)
344 * @param copy True to return a copy
345 * @returns Declaration (owned by caller if \p copy is true),
346 * or NULL if not found
349 struct ctf_field_class
*ctx_decl_scope_lookup_alias(struct ctf_visitor_generate_ir
*ctx
,
350 struct ctx_decl_scope
*scope
, const char *name
, int levels
,
353 return ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, _PREFIX_ALIAS
,
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
368 struct ctf_field_class_enum
*ctx_decl_scope_lookup_enum(struct ctf_visitor_generate_ir
*ctx
,
369 struct ctx_decl_scope
*scope
, const char *name
, int levels
,
372 return ctf_field_class_as_enum(ctx_decl_scope_lookup_prefix_alias(ctx
, scope
,
373 _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
387 struct ctf_field_class_struct
*ctx_decl_scope_lookup_struct(struct ctf_visitor_generate_ir
*ctx
,
388 struct ctx_decl_scope
*scope
, const char *name
, int levels
,
391 return ctf_field_class_as_struct(ctx_decl_scope_lookup_prefix_alias(ctx
, scope
,
392 _PREFIX_STRUCT
, name
, levels
, copy
));
396 * Looks up a variant within a declaration scope.
398 * @param scope Declaration scope
399 * @param name Variant name
400 * @param levels Number of levels to dig into (-1 means infinite)
401 * @param copy True to return a copy
402 * @returns Declaration (owned by caller if \p copy is true),
403 * or NULL if not found
406 struct ctf_field_class_variant
*ctx_decl_scope_lookup_variant(struct ctf_visitor_generate_ir
*ctx
,
407 struct ctx_decl_scope
*scope
, const char *name
, int levels
,
410 return ctf_field_class_as_variant(ctx_decl_scope_lookup_prefix_alias(ctx
, scope
,
411 _PREFIX_VARIANT
, name
, levels
, copy
));
415 * Registers a prefixed class alias within a declaration scope.
417 * @param scope Declaration scope
418 * @param prefix Prefix character
419 * @param name Alias name (non-NULL)
420 * @param decl Field class to register (copied)
421 * @returns 0 if registration went okay, negative value otherwise
424 int ctx_decl_scope_register_prefix_alias(struct ctf_visitor_generate_ir
*ctx
,
425 struct ctx_decl_scope
*scope
, char prefix
, const char *name
,
426 struct ctf_field_class
*decl
)
434 qname
= get_prefixed_named_quark(ctx
, prefix
, name
);
440 /* Make sure alias does not exist in local scope */
441 if (ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, prefix
, name
, 1,
447 decl
= ctf_field_class_copy(decl
);
449 g_hash_table_insert(scope
->decl_map
, GUINT_TO_POINTER(qname
), decl
);
456 * Registers a class alias within a declaration scope.
458 * @param scope Declaration scope
459 * @param name Alias name (non-NULL)
460 * @param decl Field class to register (copied)
461 * @returns 0 if registration went okay, negative value otherwise
464 int ctx_decl_scope_register_alias(struct ctf_visitor_generate_ir
*ctx
,
465 struct ctx_decl_scope
*scope
, const char *name
, struct ctf_field_class
*decl
)
467 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_ALIAS
,
472 * Registers an enumeration declaration within a declaration scope.
474 * @param scope Declaration scope
475 * @param name Enumeration name (non-NULL)
476 * @param decl Enumeration field class to register (copied)
477 * @returns 0 if registration went okay, negative value otherwise
480 int ctx_decl_scope_register_enum(struct ctf_visitor_generate_ir
*ctx
,
481 struct ctx_decl_scope
*scope
, const char *name
,
482 struct ctf_field_class_enum
*decl
)
484 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_ENUM
,
485 name
, &decl
->base
.base
.base
);
489 * Registers a structure declaration within a declaration scope.
491 * @param scope Declaration scope
492 * @param name Structure name (non-NULL)
493 * @param decl Structure field class to register (copied)
494 * @returns 0 if registration went okay, negative value otherwise
497 int ctx_decl_scope_register_struct(struct ctf_visitor_generate_ir
*ctx
,
498 struct ctx_decl_scope
*scope
, const char *name
,
499 struct ctf_field_class_struct
*decl
)
501 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_STRUCT
,
506 * Registers a variant declaration within a declaration scope.
508 * @param scope Declaration scope
509 * @param name Variant name (non-NULL)
510 * @param decl Variant field class to register
511 * @returns 0 if registration went okay, negative value otherwise
514 int ctx_decl_scope_register_variant(struct ctf_visitor_generate_ir
*ctx
,
515 struct ctx_decl_scope
*scope
, const char *name
,
516 struct ctf_field_class_variant
*decl
)
518 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_VARIANT
,
523 * Destroys a visitor context.
525 * @param ctx Visitor context to destroy
528 void ctx_destroy(struct ctf_visitor_generate_ir
*ctx
)
530 struct ctx_decl_scope
*scope
;
536 scope
= ctx
->current_scope
;
539 * Destroy all scopes, from current one to the root scope.
542 struct ctx_decl_scope
*parent_scope
= scope
->parent_scope
;
544 ctx_decl_scope_destroy(scope
);
545 scope
= parent_scope
;
548 bt_trace_class_put_ref(ctx
->trace_class
);
551 ctf_trace_class_destroy(ctx
->ctf_tc
);
561 * Creates a new visitor context.
563 * @param trace Associated trace
564 * @returns New visitor context, or NULL on error
567 struct ctf_visitor_generate_ir
*ctx_create(
568 const struct ctf_metadata_decoder_config
*decoder_config
)
570 struct ctf_visitor_generate_ir
*ctx
= NULL
;
572 BT_ASSERT(decoder_config
);
574 ctx
= g_new0(struct ctf_visitor_generate_ir
, 1);
576 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
,
577 decoder_config
->self_comp
,
578 "Failed to allocate one visitor context.");
582 ctx
->log_cfg
.log_level
= decoder_config
->log_level
;
583 ctx
->log_cfg
.self_comp
= decoder_config
->self_comp
;
584 ctx
->log_cfg
.self_comp_class
= decoder_config
->self_comp_class
;
586 if (decoder_config
->self_comp
) {
587 ctx
->trace_class
= bt_trace_class_create(
588 decoder_config
->self_comp
);
589 if (!ctx
->trace_class
) {
590 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create empty trace class.");
595 ctx
->ctf_tc
= ctf_trace_class_create();
597 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create CTF trace class.");
601 /* Root declaration scope */
602 ctx
->current_scope
= ctx_decl_scope_create(ctx
, NULL
);
603 if (!ctx
->current_scope
) {
604 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
608 ctx
->decoder_config
= *decoder_config
;
620 * Pushes a new declaration scope on top of a visitor context's
621 * declaration scope stack.
623 * @param ctx Visitor context
624 * @returns 0 on success, or a negative value on error
627 int ctx_push_scope(struct ctf_visitor_generate_ir
*ctx
)
630 struct ctx_decl_scope
*new_scope
;
633 new_scope
= ctx_decl_scope_create(ctx
, ctx
->current_scope
);
635 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
640 ctx
->current_scope
= new_scope
;
647 void ctx_pop_scope(struct ctf_visitor_generate_ir
*ctx
)
649 struct ctx_decl_scope
*parent_scope
= NULL
;
653 if (!ctx
->current_scope
) {
657 parent_scope
= ctx
->current_scope
->parent_scope
;
658 ctx_decl_scope_destroy(ctx
->current_scope
);
659 ctx
->current_scope
= parent_scope
;
666 int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
667 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
);
670 int is_unary_string(struct bt_list_head
*head
)
673 struct ctf_node
*node
;
675 bt_list_for_each_entry(node
, head
, siblings
) {
676 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
680 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
689 const char *get_map_clock_name_value(struct bt_list_head
*head
)
692 struct ctf_node
*node
;
693 const char *name
= NULL
;
695 bt_list_for_each_entry(node
, head
, siblings
) {
697 int uexpr_type
= node
->u
.unary_expression
.type
;
698 int uexpr_link
= node
->u
.unary_expression
.link
;
699 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
700 uexpr_type
!= UNARY_STRING
||
701 !((uexpr_link
!= UNARY_LINK_UNKNOWN
) ^ (i
== 0));
706 /* Needs to be chained with . */
707 switch (node
->u
.unary_expression
.link
) {
710 case UNARY_ARROWLINK
:
711 case UNARY_DOTDOTDOT
:
717 src_string
= node
->u
.unary_expression
.u
.string
;
721 if (strcmp("clock", src_string
)) {
729 if (strcmp("value", src_string
)) {
734 /* Extra identifier, unknown */
748 int is_unary_unsigned(struct bt_list_head
*head
)
751 struct ctf_node
*node
;
753 bt_list_for_each_entry(node
, head
, siblings
) {
754 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
758 if (node
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
767 int get_unary_unsigned(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
772 struct ctf_node
*node
;
776 if (bt_list_empty(head
)) {
781 bt_list_for_each_entry(node
, head
, siblings
) {
782 int uexpr_type
= node
->u
.unary_expression
.type
;
783 int uexpr_link
= node
->u
.unary_expression
.link
;
784 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
785 uexpr_type
!= UNARY_UNSIGNED_CONSTANT
||
786 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
788 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid constant unsigned integer.");
793 *value
= node
->u
.unary_expression
.u
.unsigned_constant
;
802 int is_unary_signed(struct bt_list_head
*head
)
805 struct ctf_node
*node
;
807 bt_list_for_each_entry(node
, head
, siblings
) {
808 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
812 if (node
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
) {
821 int get_unary_signed(struct bt_list_head
*head
, int64_t *value
)
825 struct ctf_node
*node
;
827 bt_list_for_each_entry(node
, head
, siblings
) {
828 int uexpr_type
= node
->u
.unary_expression
.type
;
829 int uexpr_link
= node
->u
.unary_expression
.link
;
830 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
831 (uexpr_type
!= UNARY_UNSIGNED_CONSTANT
&&
832 uexpr_type
!= UNARY_SIGNED_CONSTANT
) ||
833 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
839 switch (uexpr_type
) {
840 case UNARY_UNSIGNED_CONSTANT
:
842 node
->u
.unary_expression
.u
.unsigned_constant
;
844 case UNARY_SIGNED_CONSTANT
:
845 *value
= node
->u
.unary_expression
.u
.signed_constant
;
860 int get_unary_uuid(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
863 return ctf_ast_get_unary_uuid(head
, uuid
, ctx
->log_cfg
.log_level
,
864 ctx
->log_cfg
.self_comp
);
868 int get_boolean(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*unary_expr
)
872 if (unary_expr
->type
!= NODE_UNARY_EXPRESSION
) {
873 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
874 "Expecting unary expression: node-type=%d",
880 switch (unary_expr
->u
.unary_expression
.type
) {
881 case UNARY_UNSIGNED_CONSTANT
:
882 ret
= (unary_expr
->u
.unary_expression
.u
.unsigned_constant
!= 0);
884 case UNARY_SIGNED_CONSTANT
:
885 ret
= (unary_expr
->u
.unary_expression
.u
.signed_constant
!= 0);
889 const char *str
= unary_expr
->u
.unary_expression
.u
.string
;
891 if (strcmp(str
, "true") == 0 || strcmp(str
, "TRUE") == 0) {
893 } else if (strcmp(str
, "false") == 0 || strcmp(str
, "FALSE") == 0) {
896 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
897 "Unexpected boolean value: value=\"%s\"", str
);
904 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
905 "Unexpected unary expression type: node-type=%d",
906 unary_expr
->u
.unary_expression
.type
);
916 enum ctf_byte_order
byte_order_from_unary_expr(struct ctf_visitor_generate_ir
*ctx
,
917 struct ctf_node
*unary_expr
)
920 enum ctf_byte_order bo
= CTF_BYTE_ORDER_UNKNOWN
;
922 if (unary_expr
->u
.unary_expression
.type
!= UNARY_STRING
) {
923 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
924 "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
928 str
= unary_expr
->u
.unary_expression
.u
.string
;
930 if (strcmp(str
, "be") == 0 || strcmp(str
, "network") == 0) {
931 bo
= CTF_BYTE_ORDER_BIG
;
932 } else if (strcmp(str
, "le") == 0) {
933 bo
= CTF_BYTE_ORDER_LITTLE
;
934 } else if (strcmp(str
, "native") == 0) {
935 bo
= CTF_BYTE_ORDER_DEFAULT
;
937 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
938 "Unexpected \"byte_order\" attribute value: "
939 "expecting `be`, `le`, `network`, or `native`: value=\"%s\"",
949 enum ctf_byte_order
get_real_byte_order(struct ctf_visitor_generate_ir
*ctx
,
950 struct ctf_node
*uexpr
)
952 enum ctf_byte_order bo
= byte_order_from_unary_expr(ctx
, uexpr
);
954 if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
955 bo
= ctx
->ctf_tc
->default_byte_order
;
962 int is_align_valid(uint64_t align
)
964 return (align
!= 0) && !(align
& (align
- UINT64_C(1)));
968 int get_class_specifier_name(struct ctf_visitor_generate_ir
*ctx
,
969 struct ctf_node
*cls_specifier
, GString
*str
)
973 if (cls_specifier
->type
!= NODE_TYPE_SPECIFIER
) {
974 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
,
975 "Unexpected node type: node-type=%d",
976 cls_specifier
->type
);
981 switch (cls_specifier
->u
.field_class_specifier
.type
) {
983 g_string_append(str
, "void");
986 g_string_append(str
, "char");
989 g_string_append(str
, "short");
992 g_string_append(str
, "int");
995 g_string_append(str
, "long");
998 g_string_append(str
, "float");
1000 case TYPESPEC_DOUBLE
:
1001 g_string_append(str
, "double");
1003 case TYPESPEC_SIGNED
:
1004 g_string_append(str
, "signed");
1006 case TYPESPEC_UNSIGNED
:
1007 g_string_append(str
, "unsigned");
1010 g_string_append(str
, "bool");
1012 case TYPESPEC_COMPLEX
:
1013 g_string_append(str
, "_Complex");
1015 case TYPESPEC_IMAGINARY
:
1016 g_string_append(str
, "_Imaginary");
1018 case TYPESPEC_CONST
:
1019 g_string_append(str
, "const");
1021 case TYPESPEC_ID_TYPE
:
1022 if (cls_specifier
->u
.field_class_specifier
.id_type
) {
1023 g_string_append(str
,
1024 cls_specifier
->u
.field_class_specifier
.id_type
);
1027 case TYPESPEC_STRUCT
:
1029 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1031 if (!node
->u
._struct
.name
) {
1032 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty structure field class name.");
1037 g_string_append(str
, "struct ");
1038 g_string_append(str
, node
->u
._struct
.name
);
1041 case TYPESPEC_VARIANT
:
1043 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1045 if (!node
->u
.variant
.name
) {
1046 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty variant field class name.");
1051 g_string_append(str
, "variant ");
1052 g_string_append(str
, node
->u
.variant
.name
);
1057 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1059 if (!node
->u
._enum
.enum_id
) {
1060 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
1061 "Unexpected empty enumeration field class (`enum`) name.");
1066 g_string_append(str
, "enum ");
1067 g_string_append(str
, node
->u
._enum
.enum_id
);
1070 case TYPESPEC_FLOATING_POINT
:
1071 case TYPESPEC_INTEGER
:
1072 case TYPESPEC_STRING
:
1074 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
->u
.field_class_specifier
.node
,
1075 "Unexpected field class specifier type: %d",
1076 cls_specifier
->u
.field_class_specifier
.type
);
1086 int get_class_specifier_list_name(struct ctf_visitor_generate_ir
*ctx
,
1087 struct ctf_node
*cls_specifier_list
, GString
*str
)
1090 struct ctf_node
*iter
;
1091 int alias_item_nr
= 0;
1092 struct bt_list_head
*head
=
1093 &cls_specifier_list
->u
.field_class_specifier_list
.head
;
1095 bt_list_for_each_entry(iter
, head
, siblings
) {
1096 if (alias_item_nr
!= 0) {
1097 g_string_append(str
, " ");
1101 ret
= get_class_specifier_name(ctx
, iter
, str
);
1112 GQuark
create_class_alias_identifier(struct ctf_visitor_generate_ir
*ctx
,
1113 struct ctf_node
*cls_specifier_list
,
1114 struct ctf_node
*node_field_class_declarator
)
1120 struct ctf_node
*iter
;
1121 struct bt_list_head
*pointers
=
1122 &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1124 str
= g_string_new("");
1125 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
1127 g_string_free(str
, TRUE
);
1131 bt_list_for_each_entry(iter
, pointers
, siblings
) {
1132 g_string_append(str
, " *");
1134 if (iter
->u
.pointer
.const_qualifier
) {
1135 g_string_append(str
, " const");
1139 str_c
= g_string_free(str
, FALSE
);
1140 qalias
= g_quark_from_string(str_c
);
1148 int visit_field_class_declarator(struct ctf_visitor_generate_ir
*ctx
,
1149 struct ctf_node
*cls_specifier_list
,
1150 GQuark
*field_name
, struct ctf_node
*node_field_class_declarator
,
1151 struct ctf_field_class
**field_decl
,
1152 struct ctf_field_class
*nested_decl
)
1155 * During this whole function, nested_decl is always OURS,
1156 * whereas field_decl is an output which we create, but
1157 * belongs to the caller (it is moved).
1162 /* Validate field class declarator node */
1163 if (node_field_class_declarator
) {
1164 if (node_field_class_declarator
->u
.field_class_declarator
.type
==
1166 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1167 "Unexpected field class declarator type: type=%d",
1168 node_field_class_declarator
->u
.field_class_declarator
.type
);
1173 /* TODO: GCC bitfields not supported yet */
1174 if (node_field_class_declarator
->u
.field_class_declarator
.bitfield_len
!=
1176 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1177 "GCC bitfields are not supported as of this version.");
1183 /* Find the right nested declaration if not provided */
1185 struct bt_list_head
*pointers
=
1186 &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1188 if (node_field_class_declarator
&& !bt_list_empty(pointers
)) {
1192 * If we have a pointer declarator, it HAS to
1193 * be present in the field class aliases (else
1196 qalias
= create_class_alias_identifier(ctx
,
1197 cls_specifier_list
, node_field_class_declarator
);
1199 ctx_decl_scope_lookup_alias(ctx
,
1201 g_quark_to_string(qalias
), -1, true);
1203 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1204 "Cannot find class alias: name=\"%s\"",
1205 g_quark_to_string(qalias
));
1210 if (nested_decl
->type
== CTF_FIELD_CLASS_TYPE_INT
) {
1211 /* Pointer: force integer's base to 16 */
1212 struct ctf_field_class_int
*int_fc
=
1213 ctf_field_class_as_int(nested_decl
);
1216 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
1219 ret
= visit_field_class_specifier_list(ctx
,
1220 cls_specifier_list
, &nested_decl
);
1222 BT_ASSERT(!nested_decl
);
1228 BT_ASSERT(nested_decl
);
1230 if (!node_field_class_declarator
) {
1231 *field_decl
= nested_decl
;
1236 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_ID
) {
1237 if (node_field_class_declarator
->u
.field_class_declarator
.u
.id
) {
1239 node_field_class_declarator
->u
.field_class_declarator
.u
.id
;
1241 *field_name
= g_quark_from_string(id
);
1246 *field_decl
= nested_decl
;
1250 struct ctf_node
*first
;
1251 struct ctf_field_class
*decl
= NULL
;
1252 struct ctf_field_class
*outer_field_decl
= NULL
;
1253 struct bt_list_head
*length
=
1254 &node_field_class_declarator
->
1255 u
.field_class_declarator
.u
.nested
.length
;
1257 /* Create array/sequence, pass nested_decl as child */
1258 if (bt_list_empty(length
)) {
1259 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1260 "Expecting length field reference or value.");
1265 first
= _BT_LIST_FIRST_ENTRY(length
, struct ctf_node
, siblings
);
1266 if (first
->type
!= NODE_UNARY_EXPRESSION
) {
1267 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
,
1268 "Unexpected node type: node-type=%d",
1274 switch (first
->u
.unary_expression
.type
) {
1275 case UNARY_UNSIGNED_CONSTANT
:
1277 struct ctf_field_class_array
*array_decl
= NULL
;
1279 array_decl
= ctf_field_class_array_create();
1280 BT_ASSERT(array_decl
);
1281 array_decl
->length
=
1282 first
->u
.unary_expression
.u
.unsigned_constant
;
1283 array_decl
->base
.elem_fc
= nested_decl
;
1285 decl
= &array_decl
->base
.base
;
1290 /* Lookup unsigned integer definition, create seq. */
1291 struct ctf_field_class_sequence
*seq_decl
= NULL
;
1292 char *length_name
= ctf_ast_concatenate_unary_strings(length
);
1295 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1296 "Cannot concatenate unary strings.");
1301 if (strncmp(length_name
, "env.", 4) == 0) {
1302 /* This is, in fact, an array */
1303 const char *env_entry_name
= &length_name
[4];
1304 struct ctf_trace_class_env_entry
*env_entry
=
1305 ctf_trace_class_borrow_env_entry_by_name(
1306 ctx
->ctf_tc
, env_entry_name
);
1307 struct ctf_field_class_array
*array_decl
;
1310 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1311 "Cannot find environment entry: "
1312 "name=\"%s\"", env_entry_name
);
1317 if (env_entry
->type
!= CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
) {
1318 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1319 "Wrong environment entry type "
1320 "(expecting integer): "
1321 "name=\"%s\"", env_entry_name
);
1326 if (env_entry
->value
.i
< 0) {
1327 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1328 "Invalid, negative array length: "
1329 "env-entry-name=\"%s\", "
1332 env_entry
->value
.i
);
1337 array_decl
= ctf_field_class_array_create();
1338 BT_ASSERT(array_decl
);
1339 array_decl
->length
=
1340 (uint64_t) env_entry
->value
.i
;
1341 array_decl
->base
.elem_fc
= nested_decl
;
1343 decl
= &array_decl
->base
.base
;
1345 seq_decl
= ctf_field_class_sequence_create();
1346 BT_ASSERT(seq_decl
);
1347 seq_decl
->base
.elem_fc
= nested_decl
;
1349 g_string_assign(seq_decl
->length_ref
,
1351 decl
= &seq_decl
->base
.base
;
1354 g_free(length_name
);
1362 BT_ASSERT(!nested_decl
);
1364 BT_ASSERT(!*field_decl
);
1367 * At this point, we found the next nested declaration.
1368 * We currently own this (and lost the ownership of
1369 * nested_decl in the meantime). Pass this next
1370 * nested declaration as the content of the outer
1371 * container, MOVING its ownership.
1373 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
,
1375 node_field_class_declarator
->
1376 u
.field_class_declarator
.u
.nested
.field_class_declarator
,
1377 &outer_field_decl
, decl
);
1380 BT_ASSERT(!outer_field_decl
);
1385 BT_ASSERT(outer_field_decl
);
1386 *field_decl
= outer_field_decl
;
1387 outer_field_decl
= NULL
;
1390 BT_ASSERT(*field_decl
);
1394 ctf_field_class_destroy(*field_decl
);
1402 ctf_field_class_destroy(nested_decl
);
1408 int visit_struct_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1409 struct ctf_field_class_struct
*struct_decl
,
1410 struct ctf_node
*cls_specifier_list
,
1411 struct bt_list_head
*field_class_declarators
)
1414 struct ctf_node
*iter
;
1415 struct ctf_field_class
*field_decl
= NULL
;
1417 bt_list_for_each_entry(iter
, field_class_declarators
, siblings
) {
1420 const char *field_name
;
1422 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
,
1423 &qfield_name
, iter
, &field_decl
, NULL
);
1425 BT_ASSERT(!field_decl
);
1426 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1427 "Cannot visit field class declarator: ret=%d", ret
);
1431 BT_ASSERT(field_decl
);
1432 field_name
= g_quark_to_string(qfield_name
);
1434 /* Check if field with same name already exists */
1435 if (ctf_field_class_struct_borrow_member_by_name(
1436 struct_decl
, field_name
)) {
1437 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1438 "Duplicate field in structure field class: "
1439 "field-name=\"%s\"", field_name
);
1444 /* Add field to structure */
1445 ctf_field_class_struct_append_member(struct_decl
,
1446 field_name
, field_decl
);
1453 ctf_field_class_destroy(field_decl
);
1459 int visit_variant_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1460 struct ctf_field_class_variant
*variant_decl
,
1461 struct ctf_node
*cls_specifier_list
,
1462 struct bt_list_head
*field_class_declarators
)
1465 struct ctf_node
*iter
;
1466 struct ctf_field_class
*field_decl
= NULL
;
1468 bt_list_for_each_entry(iter
, field_class_declarators
, siblings
) {
1471 const char *field_name
;
1473 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
,
1474 &qfield_name
, iter
, &field_decl
, NULL
);
1476 BT_ASSERT(!field_decl
);
1477 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1478 "Cannot visit field class declarator: ret=%d", ret
);
1482 BT_ASSERT(field_decl
);
1483 field_name
= g_quark_to_string(qfield_name
);
1485 /* Check if field with same name already exists */
1486 if (ctf_field_class_variant_borrow_option_by_name(
1487 variant_decl
, field_name
)) {
1488 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1489 "Duplicate field in variant field class: "
1490 "field-name=\"%s\"", field_name
);
1495 /* Add field to structure */
1496 ctf_field_class_variant_append_option(variant_decl
,
1497 field_name
, field_decl
);
1504 ctf_field_class_destroy(field_decl
);
1510 int visit_field_class_def(struct ctf_visitor_generate_ir
*ctx
,
1511 struct ctf_node
*cls_specifier_list
,
1512 struct bt_list_head
*field_class_declarators
)
1516 struct ctf_node
*iter
;
1517 struct ctf_field_class
*class_decl
= NULL
;
1519 bt_list_for_each_entry(iter
, field_class_declarators
, siblings
) {
1520 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
,
1521 &qidentifier
, iter
, &class_decl
, NULL
);
1523 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1524 "Cannot visit field class declarator: ret=%d", ret
);
1529 /* Do not allow field class def and alias of untagged variants */
1530 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1531 struct ctf_field_class_variant
*var_fc
=
1532 ctf_field_class_as_variant(class_decl
);
1534 if (var_fc
->tag_path
.path
->len
== 0) {
1535 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1536 "Type definition of untagged variant field class is not allowed.");
1542 ret
= ctx_decl_scope_register_alias(ctx
, ctx
->current_scope
,
1543 g_quark_to_string(qidentifier
), class_decl
);
1545 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1546 "Cannot register field class alias: name=\"%s\"",
1547 g_quark_to_string(qidentifier
));
1553 ctf_field_class_destroy(class_decl
);
1559 int visit_field_class_alias(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*target
,
1560 struct ctf_node
*alias
)
1564 struct ctf_node
*node
;
1565 GQuark qdummy_field_name
;
1566 struct ctf_field_class
*class_decl
= NULL
;
1568 /* Create target field class */
1569 if (bt_list_empty(&target
->u
.field_class_alias_target
.field_class_declarators
)) {
1572 node
= _BT_LIST_FIRST_ENTRY(
1573 &target
->u
.field_class_alias_target
.field_class_declarators
,
1574 struct ctf_node
, siblings
);
1577 ret
= visit_field_class_declarator(ctx
,
1578 target
->u
.field_class_alias_target
.field_class_specifier_list
,
1579 &qdummy_field_name
, node
, &class_decl
, NULL
);
1581 BT_ASSERT(!class_decl
);
1582 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
1583 "Cannot visit field class declarator: ret=%d", ret
);
1587 /* Do not allow field class def and alias of untagged variants */
1588 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1589 struct ctf_field_class_variant
*var_fc
=
1590 ctf_field_class_as_variant(class_decl
);
1592 if (var_fc
->tag_path
.path
->len
== 0) {
1593 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target
,
1594 "Type definition of untagged variant field class is not allowed.");
1601 * The semantic validator does not check whether the target is
1602 * abstract or not (if it has an identifier). Check it here.
1604 if (qdummy_field_name
!= 0) {
1605 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target
,
1606 "Expecting empty identifier: id=\"%s\"",
1607 g_quark_to_string(qdummy_field_name
));
1612 /* Create alias identifier */
1613 node
= _BT_LIST_FIRST_ENTRY(&alias
->u
.field_class_alias_name
.field_class_declarators
,
1614 struct ctf_node
, siblings
);
1615 qalias
= create_class_alias_identifier(ctx
,
1616 alias
->u
.field_class_alias_name
.field_class_specifier_list
, node
);
1617 ret
= ctx_decl_scope_register_alias(ctx
, ctx
->current_scope
,
1618 g_quark_to_string(qalias
), class_decl
);
1620 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
1621 "Cannot register class alias: name=\"%s\"",
1622 g_quark_to_string(qalias
));
1627 ctf_field_class_destroy(class_decl
);
1633 int visit_struct_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
1634 struct ctf_field_class_struct
*struct_decl
)
1638 switch (entry_node
->type
) {
1640 ret
= visit_field_class_def(ctx
,
1641 entry_node
->u
.field_class_def
.field_class_specifier_list
,
1642 &entry_node
->u
.field_class_def
.field_class_declarators
);
1644 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1645 "Cannot add field class found in structure field class: ret=%d",
1650 case NODE_TYPEALIAS
:
1651 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1652 entry_node
->u
.field_class_alias
.alias
);
1654 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1655 "Cannot add field class alias found in structure field class: ret=%d",
1660 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1662 ret
= visit_struct_decl_field(ctx
, struct_decl
,
1663 entry_node
->u
.struct_or_variant_declaration
.
1664 field_class_specifier_list
,
1665 &entry_node
->u
.struct_or_variant_declaration
.
1666 field_class_declarators
);
1672 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1673 "Unexpected node type: node-type=%d", entry_node
->type
);
1683 int visit_variant_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
1684 struct ctf_field_class_variant
*variant_decl
)
1688 switch (entry_node
->type
) {
1690 ret
= visit_field_class_def(ctx
,
1691 entry_node
->u
.field_class_def
.field_class_specifier_list
,
1692 &entry_node
->u
.field_class_def
.field_class_declarators
);
1694 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1695 "Cannot add field class found in variant field class: ret=%d",
1700 case NODE_TYPEALIAS
:
1701 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1702 entry_node
->u
.field_class_alias
.alias
);
1704 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1705 "Cannot add field class alias found in variant field class: ret=%d",
1710 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1712 ret
= visit_variant_decl_field(ctx
, variant_decl
,
1713 entry_node
->u
.struct_or_variant_declaration
.
1714 field_class_specifier_list
,
1715 &entry_node
->u
.struct_or_variant_declaration
.
1716 field_class_declarators
);
1722 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1723 "Unexpected node type: node-type=%d",
1734 int visit_struct_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1735 struct bt_list_head
*decl_list
, int has_body
,
1736 struct bt_list_head
*min_align
,
1737 struct ctf_field_class_struct
**struct_decl
)
1741 BT_ASSERT(struct_decl
);
1742 *struct_decl
= NULL
;
1744 /* For named struct (without body), lookup in declaration scope */
1747 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless structure field class: missing name.");
1752 *struct_decl
= ctx_decl_scope_lookup_struct(ctx
, ctx
->current_scope
,
1754 if (!*struct_decl
) {
1755 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find structure field class: name=\"struct %s\"",
1761 struct ctf_node
*entry_node
;
1762 uint64_t min_align_value
= 0;
1765 if (ctx_decl_scope_lookup_struct(ctx
,
1766 ctx
->current_scope
, name
, 1, false)) {
1767 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Structure field class already declared in local scope: "
1768 "name=\"struct %s\"", name
);
1774 if (!bt_list_empty(min_align
)) {
1775 ret
= get_unary_unsigned(ctx
, min_align
,
1778 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Unexpected unary expression for structure field class's `align` attribute: "
1784 *struct_decl
= ctf_field_class_struct_create();
1785 BT_ASSERT(*struct_decl
);
1787 if (min_align_value
!= 0) {
1788 (*struct_decl
)->base
.alignment
= min_align_value
;
1791 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1793 bt_list_for_each_entry(entry_node
, decl_list
, siblings
) {
1794 ret
= visit_struct_decl_entry(ctx
, entry_node
,
1797 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1798 "Cannot visit structure field class entry: "
1808 ret
= ctx_decl_scope_register_struct(ctx
,
1809 ctx
->current_scope
, name
, *struct_decl
);
1811 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register structure field class in declaration scope: "
1812 "name=\"struct %s\", ret=%d", name
, ret
);
1821 ctf_field_class_destroy(&(*struct_decl
)->base
);
1822 *struct_decl
= NULL
;
1827 int visit_variant_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1828 const char *tag
, struct bt_list_head
*decl_list
,
1829 int has_body
, struct ctf_field_class_variant
**variant_decl
)
1832 struct ctf_field_class_variant
*untagged_variant_decl
= NULL
;
1834 BT_ASSERT(variant_decl
);
1835 *variant_decl
= NULL
;
1837 /* For named variant (without body), lookup in declaration scope */
1840 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name.");
1845 untagged_variant_decl
=
1846 ctx_decl_scope_lookup_variant(ctx
, ctx
->current_scope
,
1848 if (!untagged_variant_decl
) {
1849 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find variant field class: name=\"variant %s\"",
1855 struct ctf_node
*entry_node
;
1858 if (ctx_decl_scope_lookup_variant(ctx
,
1859 ctx
->current_scope
, name
, 1, false)) {
1860 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Variant field class already declared in local scope: "
1861 "name=\"variant %s\"", name
);
1867 untagged_variant_decl
= ctf_field_class_variant_create();
1868 BT_ASSERT(untagged_variant_decl
);
1869 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1871 bt_list_for_each_entry(entry_node
, decl_list
, siblings
) {
1872 ret
= visit_variant_decl_entry(ctx
, entry_node
,
1873 untagged_variant_decl
);
1875 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1876 "Cannot visit variant field class entry: "
1886 ret
= ctx_decl_scope_register_variant(ctx
,
1887 ctx
->current_scope
, name
,
1888 untagged_variant_decl
);
1890 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register variant field class in declaration scope: "
1891 "name=\"variant %s\", ret=%d", name
, ret
);
1898 * If tagged, create tagged variant and return; otherwise
1899 * return untagged variant.
1902 *variant_decl
= untagged_variant_decl
;
1903 untagged_variant_decl
= NULL
;
1906 * At this point, we have a fresh untagged variant; nobody
1907 * else owns it. Set its tag now.
1909 g_string_assign(untagged_variant_decl
->tag_ref
, tag
);
1910 *variant_decl
= untagged_variant_decl
;
1911 untagged_variant_decl
= NULL
;
1914 BT_ASSERT(!untagged_variant_decl
);
1915 BT_ASSERT(*variant_decl
);
1919 ctf_field_class_destroy(&untagged_variant_decl
->base
);
1920 untagged_variant_decl
= NULL
;
1921 ctf_field_class_destroy(&(*variant_decl
)->base
);
1922 *variant_decl
= NULL
;
1935 int visit_enum_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*enumerator
,
1936 struct ctf_field_class_enum
*enum_decl
, struct uori
*last
)
1940 struct ctf_node
*iter
;
1941 struct uori start
= {
1953 const char *label
= enumerator
->u
.enumerator
.id
;
1954 struct bt_list_head
*values
= &enumerator
->u
.enumerator
.values
;
1956 bt_list_for_each_entry(iter
, values
, siblings
) {
1957 struct uori
*target
;
1959 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
1960 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1961 "Wrong expression for enumeration field class label: "
1962 "node-type=%d, label=\"%s\"", iter
->type
,
1974 switch (iter
->u
.unary_expression
.type
) {
1975 case UNARY_SIGNED_CONSTANT
:
1976 target
->is_signed
= true;
1978 iter
->u
.unary_expression
.u
.signed_constant
;
1980 case UNARY_UNSIGNED_CONSTANT
:
1981 target
->is_signed
= false;
1983 iter
->u
.unary_expression
.u
.unsigned_constant
;
1986 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1987 "Invalid enumeration field class entry: "
1988 "expecting constant signed or unsigned integer: "
1989 "node-type=%d, label=\"%s\"",
1990 iter
->u
.unary_expression
.type
, label
);
1996 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1997 "Invalid enumeration field class entry: label=\"%s\"",
2014 if (end
.is_signed
) {
2015 last
->value
.i
= end
.value
.i
+ 1;
2017 last
->value
.u
= end
.value
.u
+ 1;
2020 ctf_field_class_enum_map_range(enum_decl
, label
,
2021 start
.value
.u
, end
.value
.u
);
2029 int visit_enum_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
2030 struct ctf_node
*container_cls
,
2031 struct bt_list_head
*enumerator_list
,
2032 int has_body
, struct ctf_field_class_enum
**enum_decl
)
2036 struct ctf_field_class_int
*integer_decl
= NULL
;
2038 BT_ASSERT(enum_decl
);
2041 /* For named enum (without body), lookup in declaration scope */
2044 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless enumeration field class: missing name.");
2049 *enum_decl
= ctx_decl_scope_lookup_enum(ctx
, ctx
->current_scope
,
2052 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: "
2053 "name=\"enum %s\"", name
);
2058 struct ctf_node
*iter
;
2059 struct uori last_value
= {
2067 if (ctx_decl_scope_lookup_enum(ctx
, ctx
->current_scope
,
2069 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Enumeration field class already declared in local scope: "
2070 "name=\"enum %s\"", name
);
2076 if (!container_cls
) {
2077 integer_decl
= ctf_field_class_as_int(ctx_decl_scope_lookup_alias(ctx
,
2078 ctx
->current_scope
, "int", -1, true));
2079 if (!integer_decl
) {
2080 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find implicit `int` field class alias for enumeration field class.");
2085 ctf_field_class
*decl
;
2087 ret
= visit_field_class_declarator(ctx
, container_cls
,
2088 &qdummy_id
, NULL
, &decl
, NULL
);
2095 integer_decl
= ctf_field_class_as_int(decl
);
2098 BT_ASSERT(integer_decl
);
2100 if (integer_decl
->base
.base
.type
!= CTF_FIELD_CLASS_TYPE_INT
) {
2101 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Container field class for enumeration field class is not an integer field class: "
2102 "fc-type=%d", integer_decl
->base
.base
.type
);
2107 *enum_decl
= ctf_field_class_enum_create();
2108 BT_ASSERT(*enum_decl
);
2109 (*enum_decl
)->base
.base
.base
.alignment
=
2110 integer_decl
->base
.base
.alignment
;
2111 ctf_field_class_int_copy_content(
2112 &(*enum_decl
)->base
, integer_decl
);
2113 last_value
.is_signed
= (*enum_decl
)->base
.is_signed
;
2115 bt_list_for_each_entry(iter
, enumerator_list
, siblings
) {
2116 ret
= visit_enum_decl_entry(ctx
, iter
, *enum_decl
,
2119 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
2120 "Cannot visit enumeration field class entry: "
2127 ret
= ctx_decl_scope_register_enum(ctx
,
2128 ctx
->current_scope
, name
, *enum_decl
);
2130 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register enumeration field class in declaration scope: "
2140 ctf_field_class_destroy(&(*enum_decl
)->base
.base
.base
);
2144 ctf_field_class_destroy(&integer_decl
->base
.base
);
2145 integer_decl
= NULL
;
2150 int visit_field_class_specifier(struct ctf_visitor_generate_ir
*ctx
,
2151 struct ctf_node
*cls_specifier_list
,
2152 struct ctf_field_class
**decl
)
2155 GString
*str
= NULL
;
2158 str
= g_string_new("");
2159 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
2161 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2162 "Cannot get field class specifier list's name: ret=%d", ret
);
2166 *decl
= ctx_decl_scope_lookup_alias(ctx
, ctx
->current_scope
, str
->str
,
2169 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2170 "Cannot find field class alias: name=\"%s\"", str
->str
);
2178 ctf_field_class_destroy(*decl
);
2183 g_string_free(str
, TRUE
);
2190 int visit_integer_decl(struct ctf_visitor_generate_ir
*ctx
,
2191 struct bt_list_head
*expressions
,
2192 struct ctf_field_class_int
**integer_decl
)
2197 struct ctf_node
*expression
;
2198 uint64_t alignment
= 0, size
= 0;
2199 struct ctf_clock_class
*mapped_clock_class
= NULL
;
2200 enum ctf_encoding encoding
= CTF_ENCODING_NONE
;
2201 bt_field_class_integer_preferred_display_base base
=
2202 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2203 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2205 *integer_decl
= NULL
;
2207 bt_list_for_each_entry(expression
, expressions
, siblings
) {
2208 struct ctf_node
*left
, *right
;
2210 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
,
2211 struct ctf_node
, siblings
);
2212 right
= _BT_LIST_FIRST_ENTRY(
2213 &expression
->u
.ctf_expression
.right
, struct ctf_node
,
2216 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2217 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
,
2218 "Unexpected unary expression type: type=%d",
2219 left
->u
.unary_expression
.type
);
2224 if (strcmp(left
->u
.unary_expression
.u
.string
, "signed") == 0) {
2225 if (_IS_SET(&set
, _INTEGER_SIGNED_SET
)) {
2226 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "signed",
2227 "integer field class");
2232 signedness
= get_boolean(ctx
, right
);
2233 if (signedness
< 0) {
2234 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2235 "Invalid boolean value for integer field class's `signed` attribute: "
2241 _SET(&set
, _INTEGER_SIGNED_SET
);
2242 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2243 if (_IS_SET(&set
, _INTEGER_BYTE_ORDER_SET
)) {
2244 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order",
2245 "integer field class");
2250 byte_order
= get_real_byte_order(ctx
, right
);
2251 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2252 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2253 "Invalid `byte_order` attribute in integer field class: "
2259 _SET(&set
, _INTEGER_BYTE_ORDER_SET
);
2260 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "size") == 0) {
2261 if (_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2262 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "size",
2263 "integer field class");
2268 if (right
->u
.unary_expression
.type
!=
2269 UNARY_UNSIGNED_CONSTANT
) {
2270 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2271 "Invalid `size` attribute in integer field class: "
2272 "expecting unsigned constant integer: "
2274 right
->u
.unary_expression
.type
);
2279 size
= right
->u
.unary_expression
.u
.unsigned_constant
;
2281 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2282 "Invalid `size` attribute in integer field class: "
2283 "expecting positive constant integer: "
2284 "size=%" PRIu64
, size
);
2287 } else if (size
> 64) {
2288 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2289 "Invalid `size` attribute in integer field class: "
2290 "integer fields over 64 bits are not supported as of this version: "
2291 "size=%" PRIu64
, size
);
2296 _SET(&set
, _INTEGER_SIZE_SET
);
2297 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2298 if (_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2299 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align",
2300 "integer field class");
2305 if (right
->u
.unary_expression
.type
!=
2306 UNARY_UNSIGNED_CONSTANT
) {
2307 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2308 "Invalid `align` attribute in integer field class: "
2309 "expecting unsigned constant integer: "
2311 right
->u
.unary_expression
.type
);
2317 right
->u
.unary_expression
.u
.unsigned_constant
;
2318 if (!is_align_valid(alignment
)) {
2319 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2320 "Invalid `align` attribute in integer field class: "
2321 "expecting power of two: "
2322 "align=%" PRIu64
, alignment
);
2327 _SET(&set
, _INTEGER_ALIGN_SET
);
2328 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "base") == 0) {
2329 if (_IS_SET(&set
, _INTEGER_BASE_SET
)) {
2330 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "base",
2331 "integer field class");
2336 switch (right
->u
.unary_expression
.type
) {
2337 case UNARY_UNSIGNED_CONSTANT
:
2339 uint64_t constant
= right
->u
.unary_expression
.
2340 u
.unsigned_constant
;
2344 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2347 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2350 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2353 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2356 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2357 "Invalid `base` attribute in integer field class: "
2359 right
->u
.unary_expression
.u
.unsigned_constant
);
2367 char *s_right
= ctf_ast_concatenate_unary_strings(
2368 &expression
->u
.ctf_expression
.right
);
2370 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2371 "Unexpected unary expression for integer field class's `base` attribute.");
2376 if (strcmp(s_right
, "decimal") == 0 ||
2377 strcmp(s_right
, "dec") == 0 ||
2378 strcmp(s_right
, "d") == 0 ||
2379 strcmp(s_right
, "i") == 0 ||
2380 strcmp(s_right
, "u") == 0) {
2381 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2382 } else if (strcmp(s_right
, "hexadecimal") == 0 ||
2383 strcmp(s_right
, "hex") == 0 ||
2384 strcmp(s_right
, "x") == 0 ||
2385 strcmp(s_right
, "X") == 0 ||
2386 strcmp(s_right
, "p") == 0) {
2387 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2388 } else if (strcmp(s_right
, "octal") == 0 ||
2389 strcmp(s_right
, "oct") == 0 ||
2390 strcmp(s_right
, "o") == 0) {
2391 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2392 } else if (strcmp(s_right
, "binary") == 0 ||
2393 strcmp(s_right
, "b") == 0) {
2394 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2396 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2397 "Unexpected unary expression for integer field class's `base` attribute: "
2398 "base=\"%s\"", s_right
);
2408 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2409 "Invalid `base` attribute in integer field class: "
2410 "expecting unsigned constant integer or unary string.");
2415 _SET(&set
, _INTEGER_BASE_SET
);
2416 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2419 if (_IS_SET(&set
, _INTEGER_ENCODING_SET
)) {
2420 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding",
2421 "integer field class");
2426 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2427 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2428 "Invalid `encoding` attribute in integer field class: "
2429 "expecting unary string.");
2434 s_right
= ctf_ast_concatenate_unary_strings(
2435 &expression
->u
.ctf_expression
.right
);
2437 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2438 "Unexpected unary expression for integer field class's `encoding` attribute.");
2443 if (strcmp(s_right
, "UTF8") == 0 ||
2444 strcmp(s_right
, "utf8") == 0 ||
2445 strcmp(s_right
, "utf-8") == 0 ||
2446 strcmp(s_right
, "UTF-8") == 0 ||
2447 strcmp(s_right
, "ASCII") == 0 ||
2448 strcmp(s_right
, "ascii") == 0) {
2449 encoding
= CTF_ENCODING_UTF8
;
2450 } else if (strcmp(s_right
, "none") == 0) {
2451 encoding
= CTF_ENCODING_NONE
;
2453 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2454 "Invalid `encoding` attribute in integer field class: "
2455 "unknown encoding: encoding=\"%s\"",
2463 _SET(&set
, _INTEGER_ENCODING_SET
);
2464 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "map") == 0) {
2465 const char *clock_name
;
2467 if (_IS_SET(&set
, _INTEGER_MAP_SET
)) {
2468 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "map",
2469 "integer field class");
2474 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2475 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2476 "Invalid `map` attribute in integer field class: "
2477 "expecting unary string.");
2483 get_map_clock_name_value(
2484 &expression
->u
.ctf_expression
.right
);
2486 char *s_right
= ctf_ast_concatenate_unary_strings(
2487 &expression
->u
.ctf_expression
.right
);
2490 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2491 "Unexpected unary expression for integer field class's `map` attribute.");
2496 _BT_COMP_LOGE_NODE(right
,
2497 "Invalid `map` attribute in integer field class: "
2498 "cannot find clock class at this point: name=\"%s\"",
2500 _SET(&set
, _INTEGER_MAP_SET
);
2505 mapped_clock_class
=
2506 ctf_trace_class_borrow_clock_class_by_name(
2507 ctx
->ctf_tc
, clock_name
);
2508 if (!mapped_clock_class
) {
2509 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2510 "Invalid `map` attribute in integer field class: "
2511 "cannot find clock class at this point: name=\"%s\"",
2517 _SET(&set
, _INTEGER_MAP_SET
);
2519 _BT_COMP_LOGW_NODE(left
,
2520 "Unknown attribute in integer field class: "
2522 left
->u
.unary_expression
.u
.string
);
2526 if (!_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2527 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `size` attribute in integer field class.");
2532 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2533 if (size
% CHAR_BIT
) {
2534 /* Bit-packed alignment */
2537 /* Byte-packed alignment */
2538 alignment
= CHAR_BIT
;
2542 *integer_decl
= ctf_field_class_int_create();
2543 BT_ASSERT(*integer_decl
);
2544 (*integer_decl
)->base
.base
.alignment
= alignment
;
2545 (*integer_decl
)->base
.byte_order
= byte_order
;
2546 (*integer_decl
)->base
.size
= size
;
2547 (*integer_decl
)->is_signed
= (signedness
> 0);
2548 (*integer_decl
)->disp_base
= base
;
2549 (*integer_decl
)->encoding
= encoding
;
2550 (*integer_decl
)->mapped_clock_class
= mapped_clock_class
;
2554 ctf_field_class_destroy(&(*integer_decl
)->base
.base
);
2555 *integer_decl
= NULL
;
2560 int visit_floating_point_number_decl(struct ctf_visitor_generate_ir
*ctx
,
2561 struct bt_list_head
*expressions
,
2562 struct ctf_field_class_float
**float_decl
)
2566 struct ctf_node
*expression
;
2567 uint64_t alignment
= 1, exp_dig
= 0, mant_dig
= 0;
2568 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2572 bt_list_for_each_entry(expression
, expressions
, siblings
) {
2573 struct ctf_node
*left
, *right
;
2575 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
,
2576 struct ctf_node
, siblings
);
2577 right
= _BT_LIST_FIRST_ENTRY(
2578 &expression
->u
.ctf_expression
.right
, struct ctf_node
,
2581 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2582 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
,
2583 "Unexpected unary expression type: type=%d",
2584 left
->u
.unary_expression
.type
);
2589 if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2590 if (_IS_SET(&set
, _FLOAT_BYTE_ORDER_SET
)) {
2591 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order",
2592 "floating point number field class");
2597 byte_order
= get_real_byte_order(ctx
, right
);
2598 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2599 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2600 "Invalid `byte_order` attribute in floating point number field class: "
2606 _SET(&set
, _FLOAT_BYTE_ORDER_SET
);
2607 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "exp_dig") == 0) {
2608 if (_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2609 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "exp_dig",
2610 "floating point number field class");
2615 if (right
->u
.unary_expression
.type
!=
2616 UNARY_UNSIGNED_CONSTANT
) {
2617 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2618 "Invalid `exp_dig` attribute in floating point number field class: "
2619 "expecting unsigned constant integer: "
2621 right
->u
.unary_expression
.type
);
2626 exp_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2627 _SET(&set
, _FLOAT_EXP_DIG_SET
);
2628 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "mant_dig") == 0) {
2629 if (_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2630 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "mant_dig",
2631 "floating point number field class");
2636 if (right
->u
.unary_expression
.type
!=
2637 UNARY_UNSIGNED_CONSTANT
) {
2638 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2639 "Invalid `mant_dig` attribute in floating point number field class: "
2640 "expecting unsigned constant integer: "
2642 right
->u
.unary_expression
.type
);
2647 mant_dig
= right
->u
.unary_expression
.u
.
2649 _SET(&set
, _FLOAT_MANT_DIG_SET
);
2650 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2651 if (_IS_SET(&set
, _FLOAT_ALIGN_SET
)) {
2652 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align",
2653 "floating point number field class");
2658 if (right
->u
.unary_expression
.type
!=
2659 UNARY_UNSIGNED_CONSTANT
) {
2660 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2661 "Invalid `align` attribute in floating point number field class: "
2662 "expecting unsigned constant integer: "
2664 right
->u
.unary_expression
.type
);
2669 alignment
= right
->u
.unary_expression
.u
.
2672 if (!is_align_valid(alignment
)) {
2673 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2674 "Invalid `align` attribute in floating point number field class: "
2675 "expecting power of two: "
2676 "align=%" PRIu64
, alignment
);
2681 _SET(&set
, _FLOAT_ALIGN_SET
);
2683 _BT_COMP_LOGW_NODE(left
,
2684 "Unknown attribute in floating point number field class: "
2686 left
->u
.unary_expression
.u
.string
);
2690 if (!_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2691 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `mant_dig` attribute in floating point number field class.");
2696 if (!_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2697 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `exp_dig` attribute in floating point number field class.");
2702 if (mant_dig
!= 24 && mant_dig
!= 53) {
2703 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53.");
2708 if (mant_dig
== 24 && exp_dig
!= 8) {
2709 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2714 if (mant_dig
== 53 && exp_dig
!= 11) {
2715 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2720 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2721 if ((mant_dig
+ exp_dig
) % CHAR_BIT
) {
2722 /* Bit-packed alignment */
2725 /* Byte-packed alignment */
2726 alignment
= CHAR_BIT
;
2730 *float_decl
= ctf_field_class_float_create();
2731 BT_ASSERT(*float_decl
);
2732 (*float_decl
)->base
.base
.alignment
= alignment
;
2733 (*float_decl
)->base
.byte_order
= byte_order
;
2734 (*float_decl
)->base
.size
= mant_dig
+ exp_dig
;
2738 ctf_field_class_destroy(&(*float_decl
)->base
.base
);
2744 int visit_string_decl(struct ctf_visitor_generate_ir
*ctx
,
2745 struct bt_list_head
*expressions
,
2746 struct ctf_field_class_string
**string_decl
)
2750 struct ctf_node
*expression
;
2751 enum ctf_encoding encoding
= CTF_ENCODING_UTF8
;
2753 *string_decl
= NULL
;
2755 bt_list_for_each_entry(expression
, expressions
, siblings
) {
2756 struct ctf_node
*left
, *right
;
2758 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
,
2759 struct ctf_node
, siblings
);
2760 right
= _BT_LIST_FIRST_ENTRY(
2761 &expression
->u
.ctf_expression
.right
, struct ctf_node
,
2764 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2765 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
,
2766 "Unexpected unary expression type: type=%d",
2767 left
->u
.unary_expression
.type
);
2772 if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2775 if (_IS_SET(&set
, _STRING_ENCODING_SET
)) {
2776 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding",
2777 "string field class");
2782 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2783 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2784 "Invalid `encoding` attribute in string field class: "
2785 "expecting unary string.");
2790 s_right
= ctf_ast_concatenate_unary_strings(
2791 &expression
->u
.ctf_expression
.right
);
2793 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2794 "Unexpected unary expression for string field class's `encoding` attribute.");
2799 if (strcmp(s_right
, "UTF8") == 0 ||
2800 strcmp(s_right
, "utf8") == 0 ||
2801 strcmp(s_right
, "utf-8") == 0 ||
2802 strcmp(s_right
, "UTF-8") == 0 ||
2803 strcmp(s_right
, "ASCII") == 0 ||
2804 strcmp(s_right
, "ascii") == 0) {
2805 encoding
= CTF_ENCODING_UTF8
;
2806 } else if (strcmp(s_right
, "none") == 0) {
2807 encoding
= CTF_ENCODING_NONE
;
2809 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2810 "Invalid `encoding` attribute in string field class: "
2811 "unknown encoding: encoding=\"%s\"",
2819 _SET(&set
, _STRING_ENCODING_SET
);
2821 _BT_COMP_LOGW_NODE(left
,
2822 "Unknown attribute in string field class: "
2824 left
->u
.unary_expression
.u
.string
);
2828 *string_decl
= ctf_field_class_string_create();
2829 BT_ASSERT(*string_decl
);
2830 (*string_decl
)->encoding
= encoding
;
2834 ctf_field_class_destroy(&(*string_decl
)->base
);
2835 *string_decl
= NULL
;
2840 int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
2841 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
)
2844 struct ctf_node
*first
, *node
;
2848 if (ts_list
->type
!= NODE_TYPE_SPECIFIER_LIST
) {
2849 _BT_COMP_LOGE_APPEND_CAUSE_NODE(ts_list
,
2850 "Unexpected node type: node-type=%d", ts_list
->type
);
2855 first
= _BT_LIST_FIRST_ENTRY(&ts_list
->u
.field_class_specifier_list
.head
,
2856 struct ctf_node
, siblings
);
2857 if (first
->type
!= NODE_TYPE_SPECIFIER
) {
2858 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
,
2859 "Unexpected node type: node-type=%d", first
->type
);
2864 node
= first
->u
.field_class_specifier
.node
;
2866 switch (first
->u
.field_class_specifier
.type
) {
2867 case TYPESPEC_INTEGER
: {
2868 ctf_field_class_int
*int_decl
;
2870 ret
= visit_integer_decl(ctx
, &node
->u
.integer
.expressions
,
2873 BT_ASSERT(!int_decl
);
2877 *decl
= &int_decl
->base
.base
;
2880 case TYPESPEC_FLOATING_POINT
: {
2881 ctf_field_class_float
*float_decl
;
2883 ret
= visit_floating_point_number_decl(ctx
,
2884 &node
->u
.floating_point
.expressions
, &float_decl
);
2886 BT_ASSERT(!float_decl
);
2890 *decl
= &float_decl
->base
.base
;
2893 case TYPESPEC_STRING
: {
2894 ctf_field_class_string
*string_decl
;
2896 ret
= visit_string_decl(ctx
,
2897 &node
->u
.string
.expressions
, &string_decl
);
2899 BT_ASSERT(!string_decl
);
2903 *decl
= &string_decl
->base
;
2906 case TYPESPEC_STRUCT
: {
2907 ctf_field_class_struct
*struct_decl
;
2909 ret
= visit_struct_decl(ctx
, node
->u
._struct
.name
,
2910 &node
->u
._struct
.declaration_list
,
2911 node
->u
._struct
.has_body
,
2912 &node
->u
._struct
.min_align
, &struct_decl
);
2914 BT_ASSERT(!struct_decl
);
2918 *decl
= &struct_decl
->base
;
2921 case TYPESPEC_VARIANT
: {
2922 ctf_field_class_variant
*variant_decl
;
2924 ret
= visit_variant_decl(ctx
, node
->u
.variant
.name
,
2925 node
->u
.variant
.choice
,
2926 &node
->u
.variant
.declaration_list
,
2927 node
->u
.variant
.has_body
, &variant_decl
);
2929 BT_ASSERT(!variant_decl
);
2933 *decl
= &variant_decl
->base
;
2936 case TYPESPEC_ENUM
: {
2937 ctf_field_class_enum
*enum_decl
;
2939 ret
= visit_enum_decl(ctx
, node
->u
._enum
.enum_id
,
2940 node
->u
._enum
.container_field_class
,
2941 &node
->u
._enum
.enumerator_list
,
2942 node
->u
._enum
.has_body
, &enum_decl
);
2944 BT_ASSERT(!enum_decl
);
2948 *decl
= &enum_decl
->base
.base
.base
;
2953 case TYPESPEC_SHORT
:
2956 case TYPESPEC_FLOAT
:
2957 case TYPESPEC_DOUBLE
:
2958 case TYPESPEC_SIGNED
:
2959 case TYPESPEC_UNSIGNED
:
2961 case TYPESPEC_COMPLEX
:
2962 case TYPESPEC_IMAGINARY
:
2963 case TYPESPEC_CONST
:
2964 case TYPESPEC_ID_TYPE
:
2965 ret
= visit_field_class_specifier(ctx
, ts_list
, decl
);
2967 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
,
2968 "Cannot visit field class specifier: ret=%d",
2975 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
,
2976 "Unexpected field class specifier type: node-type=%d",
2977 first
->u
.field_class_specifier
.type
);
2986 ctf_field_class_destroy(*decl
);
2992 int visit_event_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
2993 struct ctf_event_class
*event_class
, uint64_t *stream_id
,
2999 switch (node
->type
) {
3001 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3002 &node
->u
.field_class_def
.field_class_declarators
);
3004 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3005 "Cannot add field class found in event class.");
3009 case NODE_TYPEALIAS
:
3010 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3011 node
->u
.field_class_alias
.alias
);
3013 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3014 "Cannot add field class alias found in event class.");
3018 case NODE_CTF_EXPRESSION
:
3020 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3022 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3027 if (strcmp(left
, "name") == 0) {
3028 /* This is already known at this stage */
3029 if (_IS_SET(set
, _EVENT_NAME_SET
)) {
3030 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "name", "event class");
3035 _SET(set
, _EVENT_NAME_SET
);
3036 } else if (strcmp(left
, "id") == 0) {
3039 if (_IS_SET(set
, _EVENT_ID_SET
)) {
3040 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "event class");
3045 ret
= get_unary_unsigned(ctx
,
3046 &node
->u
.ctf_expression
.right
,
3048 /* Only read "id" if get_unary_unsigned() succeeded. */
3049 if (ret
|| (!ret
&& id
< 0)) {
3050 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3051 "Unexpected unary expression for event class's `id` attribute.");
3056 event_class
->id
= id
;
3057 _SET(set
, _EVENT_ID_SET
);
3058 } else if (strcmp(left
, "stream_id") == 0) {
3059 if (_IS_SET(set
, _EVENT_STREAM_ID_SET
)) {
3060 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "stream_id",
3066 ret
= get_unary_unsigned(ctx
,
3067 &node
->u
.ctf_expression
.right
, stream_id
);
3070 * Only read "stream_id" if get_unary_unsigned()
3074 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3075 "Unexpected unary expression for event class's `stream_id` attribute.");
3080 _SET(set
, _EVENT_STREAM_ID_SET
);
3081 } else if (strcmp(left
, "context") == 0) {
3082 if (_IS_SET(set
, _EVENT_CONTEXT_SET
)) {
3083 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3084 "Duplicate `context` entry in event class.");
3089 ret
= visit_field_class_specifier_list(ctx
,
3090 _BT_LIST_FIRST_ENTRY(
3091 &node
->u
.ctf_expression
.right
,
3092 struct ctf_node
, siblings
),
3093 &event_class
->spec_context_fc
);
3095 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3096 "Cannot create event class's context field class.");
3100 BT_ASSERT(event_class
->spec_context_fc
);
3101 _SET(set
, _EVENT_CONTEXT_SET
);
3102 } else if (strcmp(left
, "fields") == 0) {
3103 if (_IS_SET(set
, _EVENT_FIELDS_SET
)) {
3104 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3105 "Duplicate `fields` entry in event class.");
3110 ret
= visit_field_class_specifier_list(ctx
,
3111 _BT_LIST_FIRST_ENTRY(
3112 &node
->u
.ctf_expression
.right
,
3113 struct ctf_node
, siblings
),
3114 &event_class
->payload_fc
);
3116 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3117 "Cannot create event class's payload field class.");
3121 BT_ASSERT(event_class
->payload_fc
);
3122 _SET(set
, _EVENT_FIELDS_SET
);
3123 } else if (strcmp(left
, "loglevel") == 0) {
3124 uint64_t loglevel_value
;
3125 bool is_log_level_known
= true;
3126 bt_event_class_log_level log_level
;
3128 if (_IS_SET(set
, _EVENT_LOG_LEVEL_SET
)) {
3129 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "loglevel",
3135 ret
= get_unary_unsigned(ctx
,
3136 &node
->u
.ctf_expression
.right
, &loglevel_value
);
3138 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3139 "Unexpected unary expression for event class's `loglevel` attribute.");
3144 switch (loglevel_value
) {
3146 log_level
= BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
;
3149 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ALERT
;
3152 log_level
= BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
;
3155 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ERROR
;
3158 log_level
= BT_EVENT_CLASS_LOG_LEVEL_WARNING
;
3161 log_level
= BT_EVENT_CLASS_LOG_LEVEL_NOTICE
;
3164 log_level
= BT_EVENT_CLASS_LOG_LEVEL_INFO
;
3167 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
;
3170 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
;
3173 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
;
3176 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
;
3179 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
;
3182 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
;
3185 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
;
3188 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG
;
3191 is_log_level_known
= false;
3192 _BT_COMP_LOGW_NODE(node
, "Not setting event class's log level because its value is unknown: "
3193 "log-level=%" PRIu64
, loglevel_value
);
3196 if (is_log_level_known
) {
3197 ctf_event_class_set_log_level(event_class
, log_level
);
3200 _SET(set
, _EVENT_LOG_LEVEL_SET
);
3201 } else if (strcmp(left
, "model.emf.uri") == 0) {
3204 if (_IS_SET(set
, _EVENT_MODEL_EMF_URI_SET
)) {
3205 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "model.emf.uri",
3211 right
= ctf_ast_concatenate_unary_strings(
3212 &node
->u
.ctf_expression
.right
);
3214 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3215 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3220 if (strlen(right
) == 0) {
3221 _BT_COMP_LOGW_NODE(node
,
3222 "Not setting event class's EMF URI because it's empty.");
3224 g_string_assign(event_class
->emf_uri
,
3229 _SET(set
, _EVENT_MODEL_EMF_URI_SET
);
3231 _BT_COMP_LOGW_NODE(node
,
3232 "Unknown attribute in event class: "
3233 "attr-name=\"%s\"", left
);
3255 char *get_event_decl_name(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3259 struct ctf_node
*iter
;
3260 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3262 bt_list_for_each_entry(iter
, decl_list
, siblings
) {
3263 if (iter
->type
!= NODE_CTF_EXPRESSION
) {
3267 left
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.left
);
3269 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3270 "Cannot concatenate unary strings.");
3274 if (strcmp(left
, "name") == 0) {
3275 name
= ctf_ast_concatenate_unary_strings(
3276 &iter
->u
.ctf_expression
.right
);
3278 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3279 "Unexpected unary expression for event class's `name` attribute.");
3300 int visit_event_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3304 struct ctf_node
*iter
;
3305 uint64_t stream_id
= 0;
3306 char *event_name
= NULL
;
3307 struct ctf_event_class
*event_class
= NULL
;
3308 struct ctf_stream_class
*stream_class
= NULL
;
3309 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3310 bool pop_scope
= false;
3312 if (node
->visited
) {
3316 node
->visited
= TRUE
;
3317 event_name
= get_event_decl_name(ctx
, node
);
3319 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3320 "Missing `name` attribute in event class.");
3325 event_class
= ctf_event_class_create();
3326 BT_ASSERT(event_class
);
3327 g_string_assign(event_class
->name
, event_name
);
3328 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3331 bt_list_for_each_entry(iter
, decl_list
, siblings
) {
3332 ret
= visit_event_decl_entry(ctx
, iter
, event_class
,
3335 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit event class's entry: "
3341 if (!_IS_SET(&set
, _EVENT_STREAM_ID_SET
)) {
3343 * Allow missing stream_id if there is only a single
3346 switch (ctx
->ctf_tc
->stream_classes
->len
) {
3348 /* Create implicit stream class if there's none */
3350 stream_class
= ctf_stream_class_create();
3351 BT_ASSERT(stream_class
);
3352 stream_class
->id
= stream_id
;
3353 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
,
3357 /* Single stream class: get its ID */
3358 stream_class
= (ctf_stream_class
*) ctx
->ctf_tc
->stream_classes
->pdata
[0];
3359 stream_id
= stream_class
->id
;
3362 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3363 "Missing `stream_id` attribute in event class.");
3369 /* We have the stream ID now; get the stream class if found */
3370 if (!stream_class
) {
3371 stream_class
= ctf_trace_class_borrow_stream_class_by_id(
3372 ctx
->ctf_tc
, stream_id
);
3373 if (!stream_class
) {
3374 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3375 "Cannot find stream class at this point: "
3376 "id=%" PRId64
, stream_id
);
3382 BT_ASSERT(stream_class
);
3384 if (!_IS_SET(&set
, _EVENT_ID_SET
)) {
3385 /* Allow only one event without ID per stream */
3386 if (stream_class
->event_classes
->len
!= 0) {
3387 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3388 "Missing `id` attribute in event class.");
3394 event_class
->id
= 0;
3397 if (ctf_stream_class_borrow_event_class_by_id(stream_class
,
3399 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3400 "Duplicate event class (same ID) in the same stream class: "
3401 "id=%" PRId64
, event_class
->id
);
3406 ctf_stream_class_append_event_class(stream_class
, event_class
);
3411 ctf_event_class_destroy(event_class
);
3429 int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3430 struct ctf_field_class
*fc
)
3432 struct ctf_clock_class
*clock_class_to_map_to
= NULL
;
3433 struct ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
3435 uint64_t clock_class_count
;
3441 if (fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3442 fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3446 if (int_fc
->mapped_clock_class
) {
3447 /* Already mapped */
3451 clock_class_count
= ctx
->ctf_tc
->clock_classes
->len
;
3453 switch (clock_class_count
) {
3456 * No clock class exists in the trace at this point. Create an
3457 * implicit one at 1 GHz, named `default`, and use this clock
3460 clock_class_to_map_to
= ctf_clock_class_create();
3461 BT_ASSERT(clock_class_to_map_to
);
3462 clock_class_to_map_to
->frequency
= UINT64_C(1000000000);
3463 g_string_assign(clock_class_to_map_to
->name
, "default");
3464 BT_ASSERT(ret
== 0);
3465 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
,
3466 clock_class_to_map_to
);
3470 * Only one clock class exists in the trace at this point: use
3473 clock_class_to_map_to
= (ctf_clock_class
*) ctx
->ctf_tc
->clock_classes
->pdata
[0];
3477 * Timestamp field not mapped to a clock class and there's more
3478 * than one clock class in the trace: this is an error.
3480 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Timestamp field found with no mapped clock class, "
3481 "but there's more than one clock class in the trace at this point.");
3486 BT_ASSERT(clock_class_to_map_to
);
3487 int_fc
->mapped_clock_class
= clock_class_to_map_to
;
3494 int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3495 struct ctf_field_class
*root_fc
, const char *field_name
)
3499 struct ctf_field_class_struct
*struct_fc
= (ctf_field_class_struct
*) root_fc
;
3500 struct ctf_field_class_variant
*var_fc
= (ctf_field_class_variant
*) root_fc
;
3506 if (root_fc
->type
!= CTF_FIELD_CLASS_TYPE_STRUCT
&&
3507 root_fc
->type
!= CTF_FIELD_CLASS_TYPE_VARIANT
) {
3511 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3512 count
= struct_fc
->members
->len
;
3514 count
= var_fc
->options
->len
;
3517 for (i
= 0; i
< count
; i
++) {
3518 struct ctf_named_field_class
*named_fc
= NULL
;
3520 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3521 named_fc
= ctf_field_class_struct_borrow_member_by_index(
3523 } else if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
3524 named_fc
= ctf_field_class_variant_borrow_option_by_index(
3530 if (strcmp(named_fc
->name
->str
, field_name
) == 0) {
3531 ret
= auto_map_field_to_trace_clock_class(ctx
,
3534 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot automatically map field to trace's clock class: "
3535 "field-name=\"%s\"", field_name
);
3540 ret
= auto_map_fields_to_trace_clock_class(ctx
, named_fc
->fc
,
3543 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot automatically map structure or variant field class's fields to trace's clock class: "
3544 "field-name=\"%s\", root-field-name=\"%s\"",
3545 field_name
, named_fc
->name
->str
);
3555 int visit_stream_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3556 struct ctf_stream_class
*stream_class
, int *set
)
3561 switch (node
->type
) {
3563 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3564 &node
->u
.field_class_def
.field_class_declarators
);
3566 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3567 "Cannot add field class found in stream class.");
3571 case NODE_TYPEALIAS
:
3572 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3573 node
->u
.field_class_alias
.alias
);
3575 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3576 "Cannot add field class alias found in stream class.");
3580 case NODE_CTF_EXPRESSION
:
3582 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3584 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3589 if (strcmp(left
, "id") == 0) {
3592 if (_IS_SET(set
, _STREAM_ID_SET
)) {
3593 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id",
3594 "stream declaration");
3599 ret
= get_unary_unsigned(ctx
,
3600 &node
->u
.ctf_expression
.right
,
3603 /* Only read "id" if get_unary_unsigned() succeeded. */
3604 if (ret
|| (!ret
&& id
< 0)) {
3605 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3606 "Unexpected unary expression for stream class's `id` attribute.");
3611 if (ctf_trace_class_borrow_stream_class_by_id(
3613 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3614 "Duplicate stream class (same ID): id=%" PRId64
,
3620 stream_class
->id
= id
;
3621 _SET(set
, _STREAM_ID_SET
);
3622 } else if (strcmp(left
, "event.header") == 0) {
3623 if (_IS_SET(set
, _STREAM_EVENT_HEADER_SET
)) {
3624 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3625 "Duplicate `event.header` entry in stream class.");
3630 ret
= visit_field_class_specifier_list(ctx
,
3631 _BT_LIST_FIRST_ENTRY(
3632 &node
->u
.ctf_expression
.right
,
3633 struct ctf_node
, siblings
),
3634 &stream_class
->event_header_fc
);
3636 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3637 "Cannot create stream class's event header field class.");
3641 BT_ASSERT(stream_class
->event_header_fc
);
3642 ret
= auto_map_fields_to_trace_clock_class(ctx
,
3643 stream_class
->event_header_fc
, "timestamp");
3645 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3646 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3650 _SET(set
, _STREAM_EVENT_HEADER_SET
);
3651 } else if (strcmp(left
, "event.context") == 0) {
3652 if (_IS_SET(set
, _STREAM_EVENT_CONTEXT_SET
)) {
3653 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3654 "Duplicate `event.context` entry in stream class.");
3659 ret
= visit_field_class_specifier_list(ctx
,
3660 _BT_LIST_FIRST_ENTRY(
3661 &node
->u
.ctf_expression
.right
,
3662 struct ctf_node
, siblings
),
3663 &stream_class
->event_common_context_fc
);
3665 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3666 "Cannot create stream class's event context field class.");
3670 BT_ASSERT(stream_class
->event_common_context_fc
);
3671 _SET(set
, _STREAM_EVENT_CONTEXT_SET
);
3672 } else if (strcmp(left
, "packet.context") == 0) {
3673 if (_IS_SET(set
, _STREAM_PACKET_CONTEXT_SET
)) {
3674 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3675 "Duplicate `packet.context` entry in stream class.");
3680 ret
= visit_field_class_specifier_list(ctx
,
3681 _BT_LIST_FIRST_ENTRY(
3682 &node
->u
.ctf_expression
.right
,
3683 struct ctf_node
, siblings
),
3684 &stream_class
->packet_context_fc
);
3686 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3687 "Cannot create stream class's packet context field class.");
3691 BT_ASSERT(stream_class
->packet_context_fc
);
3692 ret
= auto_map_fields_to_trace_clock_class(ctx
,
3693 stream_class
->packet_context_fc
,
3696 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3697 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3701 ret
= auto_map_fields_to_trace_clock_class(ctx
,
3702 stream_class
->packet_context_fc
,
3705 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3706 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3710 _SET(set
, _STREAM_PACKET_CONTEXT_SET
);
3712 _BT_COMP_LOGW_NODE(node
,
3713 "Unknown attribute in stream class: "
3714 "attr-name=\"%s\"", left
);
3735 int visit_stream_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3739 struct ctf_node
*iter
;
3740 struct ctf_stream_class
*stream_class
= NULL
;
3741 struct bt_list_head
*decl_list
= &node
->u
.stream
.declaration_list
;
3743 if (node
->visited
) {
3747 node
->visited
= TRUE
;
3748 stream_class
= ctf_stream_class_create();
3749 BT_ASSERT(stream_class
);
3750 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3752 bt_list_for_each_entry(iter
, decl_list
, siblings
) {
3753 ret
= visit_stream_decl_entry(ctx
, iter
, stream_class
, &set
);
3755 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3756 "Cannot visit stream class's entry: "
3765 if (_IS_SET(&set
, _STREAM_ID_SET
)) {
3766 /* Check that packet header has `stream_id` field */
3767 struct ctf_named_field_class
*named_fc
= NULL
;
3769 if (!ctx
->ctf_tc
->packet_header_fc
) {
3770 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3771 "Stream class has a `id` attribute, "
3772 "but trace has no packet header field class.");
3777 named_fc
= ctf_field_class_struct_borrow_member_by_name(
3778 ctf_field_class_as_struct(ctx
->ctf_tc
->packet_header_fc
), "stream_id");
3780 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3781 "Stream class has a `id` attribute, "
3782 "but trace's packet header field class has no `stream_id` field.");
3787 if (named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3788 named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3789 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3790 "Stream class has a `id` attribute, "
3791 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3796 /* Allow only _one_ ID-less stream */
3797 if (ctx
->ctf_tc
->stream_classes
->len
!= 0) {
3798 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3799 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3804 /* Automatic ID: 0 */
3805 stream_class
->id
= 0;
3809 * Make sure that this stream class's ID is currently unique in
3812 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
,
3813 stream_class
->id
)) {
3814 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3815 "Duplicate stream class (same ID): id=%" PRId64
,
3821 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3822 stream_class
= NULL
;
3826 ctf_stream_class_destroy(stream_class
);
3827 stream_class
= NULL
;
3834 int visit_trace_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3841 switch (node
->type
) {
3843 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3844 &node
->u
.field_class_def
.field_class_declarators
);
3846 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3847 "Cannot add field class found in trace (`trace` block).");
3851 case NODE_TYPEALIAS
:
3852 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3853 node
->u
.field_class_alias
.alias
);
3855 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3856 "Cannot add field class alias found in trace (`trace` block).");
3860 case NODE_CTF_EXPRESSION
:
3862 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3864 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3869 if (strcmp(left
, "major") == 0) {
3870 if (_IS_SET(set
, _TRACE_MAJOR_SET
)) {
3871 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "major", "trace");
3876 ret
= get_unary_unsigned(ctx
,
3877 &node
->u
.ctf_expression
.right
, &val
);
3879 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3880 "Unexpected unary expression for trace's `major` attribute.");
3886 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3887 "Invalid trace's `minor` attribute: expecting 1.");
3892 ctx
->ctf_tc
->major
= val
;
3893 _SET(set
, _TRACE_MAJOR_SET
);
3894 } else if (strcmp(left
, "minor") == 0) {
3895 if (_IS_SET(set
, _TRACE_MINOR_SET
)) {
3896 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "minor", "trace");
3901 ret
= get_unary_unsigned(ctx
,
3902 &node
->u
.ctf_expression
.right
, &val
);
3904 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3905 "Unexpected unary expression for trace's `minor` attribute.");
3911 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3912 "Invalid trace's `minor` attribute: expecting 8.");
3917 ctx
->ctf_tc
->minor
= val
;
3918 _SET(set
, _TRACE_MINOR_SET
);
3919 } else if (strcmp(left
, "uuid") == 0) {
3920 if (_IS_SET(set
, _TRACE_UUID_SET
)) {
3921 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "uuid", "trace");
3926 ret
= get_unary_uuid(ctx
,
3927 &node
->u
.ctf_expression
.right
,
3930 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3931 "Invalid trace's `uuid` attribute.");
3935 ctx
->ctf_tc
->is_uuid_set
= true;
3936 _SET(set
, _TRACE_UUID_SET
);
3937 } else if (strcmp(left
, "byte_order") == 0) {
3938 /* Default byte order is already known at this stage */
3939 if (_IS_SET(set
, _TRACE_BYTE_ORDER_SET
)) {
3940 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order",
3946 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
!= CTF_BYTE_ORDER_UNKNOWN
);
3947 _SET(set
, _TRACE_BYTE_ORDER_SET
);
3948 } else if (strcmp(left
, "packet.header") == 0) {
3949 if (_IS_SET(set
, _TRACE_PACKET_HEADER_SET
)) {
3950 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3951 "Duplicate `packet.header` entry in trace.");
3956 ret
= visit_field_class_specifier_list(ctx
,
3957 _BT_LIST_FIRST_ENTRY(
3958 &node
->u
.ctf_expression
.right
,
3959 struct ctf_node
, siblings
),
3960 &ctx
->ctf_tc
->packet_header_fc
);
3962 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3963 "Cannot create trace's packet header field class.");
3967 BT_ASSERT(ctx
->ctf_tc
->packet_header_fc
);
3968 _SET(set
, _TRACE_PACKET_HEADER_SET
);
3970 _BT_COMP_LOGW_NODE(node
,
3971 "Unknown attribute in stream class: "
3972 "attr-name=\"%s\"", left
);
3980 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unknown expression in trace.");
3993 int visit_trace_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3997 struct ctf_node
*iter
;
3998 struct bt_list_head
*decl_list
= &node
->u
.trace
.declaration_list
;
4000 if (node
->visited
) {
4004 node
->visited
= TRUE
;
4006 if (ctx
->is_trace_visited
) {
4007 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
4012 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
4014 bt_list_for_each_entry(iter
, decl_list
, siblings
) {
4015 ret
= visit_trace_decl_entry(ctx
, iter
, &set
);
4017 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit trace's entry (`trace` block): "
4026 if (!_IS_SET(&set
, _TRACE_MAJOR_SET
)) {
4027 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4028 "Missing `major` attribute in trace (`trace` block).");
4033 if (!_IS_SET(&set
, _TRACE_MINOR_SET
)) {
4034 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4035 "Missing `minor` attribute in trace (`trace` block).");
4040 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4041 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4042 "Missing `byte_order` attribute in trace (`trace` block).");
4047 ctx
->is_trace_visited
= true;
4057 int visit_env(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
4061 struct ctf_node
*entry_node
;
4062 struct bt_list_head
*decl_list
= &node
->u
.env
.declaration_list
;
4064 if (node
->visited
) {
4068 node
->visited
= TRUE
;
4070 bt_list_for_each_entry(entry_node
, decl_list
, siblings
) {
4071 struct bt_list_head
*right_head
=
4072 &entry_node
->u
.ctf_expression
.right
;
4074 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4075 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4076 "Wrong expression in environment entry: "
4077 "node-type=%d", entry_node
->type
);
4082 left
= ctf_ast_concatenate_unary_strings(
4083 &entry_node
->u
.ctf_expression
.left
);
4085 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4086 "Cannot get environment entry's name.");
4091 if (is_unary_string(right_head
)) {
4092 char *right
= ctf_ast_concatenate_unary_strings(right_head
);
4095 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4096 "Unexpected unary expression for environment entry's value: "
4097 "name=\"%s\"", left
);
4102 if (strcmp(left
, "tracer_name") == 0) {
4103 if (strncmp(right
, "lttng", 5) == 0) {
4104 BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: "
4105 "tracer-name=\"%s\"",
4107 ctx
->is_lttng
= true;
4111 ctf_trace_class_append_env_entry(ctx
->ctf_tc
,
4112 left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
,
4115 } else if (is_unary_unsigned(right_head
) ||
4116 is_unary_signed(right_head
)) {
4119 if (is_unary_unsigned(right_head
)) {
4120 ret
= get_unary_unsigned(ctx
, right_head
,
4123 ret
= get_unary_signed(right_head
, &v
);
4126 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4127 "Unexpected unary expression for environment entry's value: "
4128 "name=\"%s\"", left
);
4133 ctf_trace_class_append_env_entry(ctx
->ctf_tc
,
4134 left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
,
4137 _BT_COMP_LOGW_NODE(entry_node
,
4138 "Environment entry has unknown type: "
4139 "name=\"%s\"", left
);
4155 int set_trace_byte_order(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*trace_node
)
4160 struct ctf_node
*node
;
4161 struct bt_list_head
*decl_list
= &trace_node
->u
.trace
.declaration_list
;
4163 bt_list_for_each_entry(node
, decl_list
, siblings
) {
4164 if (node
->type
== NODE_CTF_EXPRESSION
) {
4165 struct ctf_node
*right_node
;
4167 left
= ctf_ast_concatenate_unary_strings(
4168 &node
->u
.ctf_expression
.left
);
4170 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4171 "Cannot concatenate unary strings.");
4176 if (strcmp(left
, "byte_order") == 0) {
4177 enum ctf_byte_order bo
;
4179 if (_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4180 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order",
4186 _SET(&set
, _TRACE_BYTE_ORDER_SET
);
4187 right_node
= _BT_LIST_FIRST_ENTRY(
4188 &node
->u
.ctf_expression
.right
,
4189 struct ctf_node
, siblings
);
4190 bo
= byte_order_from_unary_expr(ctx
,
4192 if (bo
== CTF_BYTE_ORDER_UNKNOWN
) {
4193 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4194 "Invalid `byte_order` attribute in trace (`trace` block): "
4195 "expecting `le`, `be`, or `network`.");
4198 } else if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
4199 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4200 "Invalid `byte_order` attribute in trace (`trace` block): "
4201 "cannot be set to `native` here.");
4206 ctx
->ctf_tc
->default_byte_order
= bo
;
4214 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4215 _BT_COMP_LOGE_APPEND_CAUSE_NODE(trace_node
,
4216 "Missing `byte_order` attribute in trace (`trace` block).");
4229 int visit_clock_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
4230 struct ctf_clock_class
*clock
, int *set
, int64_t *offset_seconds
,
4231 uint64_t *offset_cycles
)
4236 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4237 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4238 "Unexpected node type: node-type=%d",
4244 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
4246 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot concatenate unary strings.");
4251 if (strcmp(left
, "name") == 0) {
4254 if (_IS_SET(set
, _CLOCK_NAME_SET
)) {
4255 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "name", "clock class");
4260 right
= ctf_ast_concatenate_unary_strings(
4261 &entry_node
->u
.ctf_expression
.right
);
4263 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4264 "Unexpected unary expression for clock class's `name` attribute.");
4269 g_string_assign(clock
->name
, right
);
4271 _SET(set
, _CLOCK_NAME_SET
);
4272 } else if (strcmp(left
, "uuid") == 0) {
4275 if (_IS_SET(set
, _CLOCK_UUID_SET
)) {
4276 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "uuid", "clock class");
4281 ret
= get_unary_uuid(ctx
, &entry_node
->u
.ctf_expression
.right
,
4284 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4285 "Invalid clock class's `uuid` attribute.");
4289 clock
->has_uuid
= true;
4290 bt_uuid_copy(clock
->uuid
, uuid
);
4291 _SET(set
, _CLOCK_UUID_SET
);
4292 } else if (strcmp(left
, "description") == 0) {
4295 if (_IS_SET(set
, _CLOCK_DESCRIPTION_SET
)) {
4296 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "description",
4302 right
= ctf_ast_concatenate_unary_strings(
4303 &entry_node
->u
.ctf_expression
.right
);
4305 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4306 "Unexpected unary expression for clock class's `description` attribute.");
4311 g_string_assign(clock
->description
, right
);
4313 _SET(set
, _CLOCK_DESCRIPTION_SET
);
4314 } else if (strcmp(left
, "freq") == 0) {
4315 uint64_t freq
= UINT64_C(-1);
4317 if (_IS_SET(set
, _CLOCK_FREQ_SET
)) {
4318 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "freq", "clock class");
4323 ret
= get_unary_unsigned(ctx
,
4324 &entry_node
->u
.ctf_expression
.right
, &freq
);
4326 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4327 "Unexpected unary expression for clock class's `freq` attribute.");
4332 if (freq
== UINT64_C(-1) || freq
== 0) {
4333 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4334 "Invalid clock class frequency: freq=%" PRIu64
,
4340 clock
->frequency
= freq
;
4341 _SET(set
, _CLOCK_FREQ_SET
);
4342 } else if (strcmp(left
, "precision") == 0) {
4345 if (_IS_SET(set
, _CLOCK_PRECISION_SET
)) {
4346 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "precision",
4352 ret
= get_unary_unsigned(ctx
,
4353 &entry_node
->u
.ctf_expression
.right
, &precision
);
4355 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4356 "Unexpected unary expression for clock class's `precision` attribute.");
4361 clock
->precision
= precision
;
4362 _SET(set
, _CLOCK_PRECISION_SET
);
4363 } else if (strcmp(left
, "offset_s") == 0) {
4364 if (_IS_SET(set
, _CLOCK_OFFSET_S_SET
)) {
4365 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset_s",
4371 ret
= get_unary_signed(
4372 &entry_node
->u
.ctf_expression
.right
, offset_seconds
);
4374 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4375 "Unexpected unary expression for clock class's `offset_s` attribute.");
4380 _SET(set
, _CLOCK_OFFSET_S_SET
);
4381 } else if (strcmp(left
, "offset") == 0) {
4382 if (_IS_SET(set
, _CLOCK_OFFSET_SET
)) {
4383 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset", "clock class");
4388 ret
= get_unary_unsigned(ctx
,
4389 &entry_node
->u
.ctf_expression
.right
, offset_cycles
);
4391 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4392 "Unexpected unary expression for clock class's `offset` attribute.");
4397 _SET(set
, _CLOCK_OFFSET_SET
);
4398 } else if (strcmp(left
, "absolute") == 0) {
4399 struct ctf_node
*right
;
4401 if (_IS_SET(set
, _CLOCK_ABSOLUTE_SET
)) {
4402 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "absolute",
4408 right
= _BT_LIST_FIRST_ENTRY(
4409 &entry_node
->u
.ctf_expression
.right
,
4410 struct ctf_node
, siblings
);
4411 ret
= get_boolean(ctx
, right
);
4413 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4414 "Unexpected unary expression for clock class's `absolute` attribute.");
4419 clock
->is_absolute
= ret
;
4420 _SET(set
, _CLOCK_ABSOLUTE_SET
);
4422 _BT_COMP_LOGW_NODE(entry_node
,
4423 "Unknown attribute in clock class: attr-name=\"%s\"",
4437 uint64_t cycles_from_ns(uint64_t frequency
, uint64_t ns
)
4442 if (frequency
== UINT64_C(1000000000)) {
4445 cycles
= (uint64_t) (((double) ns
* (double) frequency
) / 1e9
);
4452 void calibrate_clock_class_offsets(int64_t *offset_seconds
,
4453 uint64_t *offset_cycles
, uint64_t freq
)
4455 if (*offset_cycles
>= freq
) {
4456 const uint64_t s_in_offset_cycles
= *offset_cycles
/ freq
;
4458 *offset_seconds
+= (int64_t) s_in_offset_cycles
;
4459 *offset_cycles
-= (s_in_offset_cycles
* freq
);
4464 void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir
*ctx
,
4465 struct ctf_clock_class
*clock
)
4467 if (ctx
->decoder_config
.force_clock_class_origin_unix_epoch
) {
4468 clock
->is_absolute
= true;
4475 void apply_clock_class_offset(struct ctf_visitor_generate_ir
*ctx
,
4476 struct ctf_clock_class
*clock
)
4479 int64_t offset_s_to_apply
= ctx
->decoder_config
.clock_class_offset_s
;
4480 uint64_t offset_ns_to_apply
;
4481 int64_t cur_offset_s
;
4482 uint64_t cur_offset_cycles
;
4484 if (ctx
->decoder_config
.clock_class_offset_s
== 0 &&
4485 ctx
->decoder_config
.clock_class_offset_ns
== 0) {
4489 /* Transfer nanoseconds to seconds as much as possible */
4490 if (ctx
->decoder_config
.clock_class_offset_ns
< 0) {
4491 const int64_t abs_ns
= -ctx
->decoder_config
.clock_class_offset_ns
;
4492 const int64_t abs_extra_s
= abs_ns
/ INT64_C(1000000000) + 1;
4493 const int64_t extra_s
= -abs_extra_s
;
4494 const int64_t offset_ns
= ctx
->decoder_config
.clock_class_offset_ns
-
4495 (extra_s
* INT64_C(1000000000));
4497 BT_ASSERT(offset_ns
> 0);
4498 offset_ns_to_apply
= (uint64_t) offset_ns
;
4499 offset_s_to_apply
+= extra_s
;
4501 const int64_t extra_s
= ctx
->decoder_config
.clock_class_offset_ns
/
4502 INT64_C(1000000000);
4503 const int64_t offset_ns
= ctx
->decoder_config
.clock_class_offset_ns
-
4504 (extra_s
* INT64_C(1000000000));
4506 BT_ASSERT(offset_ns
>= 0);
4507 offset_ns_to_apply
= (uint64_t) offset_ns
;
4508 offset_s_to_apply
+= extra_s
;
4511 freq
= clock
->frequency
;
4512 cur_offset_s
= clock
->offset_seconds
;
4513 cur_offset_cycles
= clock
->offset_cycles
;
4516 cur_offset_s
+= offset_s_to_apply
;
4517 cur_offset_cycles
+= cycles_from_ns(freq
, offset_ns_to_apply
);
4520 * Recalibrate offsets because the part in cycles can be greater
4521 * than the frequency at this point.
4523 calibrate_clock_class_offsets(&cur_offset_s
, &cur_offset_cycles
, freq
);
4525 /* Set final offsets */
4526 clock
->offset_seconds
= cur_offset_s
;
4527 clock
->offset_cycles
= cur_offset_cycles
;
4534 int visit_clock_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*clock_node
)
4538 struct ctf_clock_class
*clock
;
4539 struct ctf_node
*entry_node
;
4540 struct bt_list_head
*decl_list
= &clock_node
->u
.clock
.declaration_list
;
4541 const char *clock_class_name
;
4542 int64_t offset_seconds
= 0;
4543 uint64_t offset_cycles
= 0;
4546 if (clock_node
->visited
) {
4550 clock_node
->visited
= TRUE
;
4552 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4553 clock
= ctf_clock_class_create();
4555 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
,
4556 "Cannot create default clock class.");
4561 bt_list_for_each_entry(entry_node
, decl_list
, siblings
) {
4562 ret
= visit_clock_decl_entry(ctx
, entry_node
, clock
, &set
,
4563 &offset_seconds
, &offset_cycles
);
4565 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4566 "Cannot visit clock class's entry: ret=%d",
4572 if (!_IS_SET(&set
, _CLOCK_NAME_SET
)) {
4573 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
,
4574 "Missing `name` attribute in clock class.");
4579 clock_class_name
= clock
->name
->str
;
4580 BT_ASSERT(clock_class_name
);
4581 if (ctx
->is_lttng
&& strcmp(clock_class_name
, "monotonic") == 0) {
4583 * Old versions of LTTng forgot to set its clock class
4584 * as absolute, even if it is. This is important because
4585 * it's a condition to be able to sort messages
4586 * from different sources.
4588 clock
->is_absolute
= true;
4592 * Adjust offsets so that the part in cycles is less than the
4593 * frequency (move to the part in seconds).
4595 freq
= clock
->frequency
;
4596 calibrate_clock_class_offsets(&offset_seconds
, &offset_cycles
, freq
);
4597 BT_ASSERT(offset_cycles
< clock
->frequency
);
4598 clock
->offset_seconds
= offset_seconds
;
4599 clock
->offset_cycles
= offset_cycles
;
4600 apply_clock_class_offset(ctx
, clock
);
4601 apply_clock_class_is_absolute(ctx
, clock
);
4602 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock
);
4607 ctf_clock_class_destroy(clock
);
4614 int visit_root_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*root_decl_node
)
4618 if (root_decl_node
->visited
) {
4622 root_decl_node
->visited
= TRUE
;
4624 switch (root_decl_node
->type
) {
4626 ret
= visit_field_class_def(ctx
,
4627 root_decl_node
->u
.field_class_def
.field_class_specifier_list
,
4628 &root_decl_node
->u
.field_class_def
.field_class_declarators
);
4630 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4631 "Cannot add field class found in root scope.");
4635 case NODE_TYPEALIAS
:
4636 ret
= visit_field_class_alias(ctx
, root_decl_node
->u
.field_class_alias
.target
,
4637 root_decl_node
->u
.field_class_alias
.alias
);
4639 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4640 "Cannot add field class alias found in root scope.");
4644 case NODE_TYPE_SPECIFIER_LIST
:
4646 struct ctf_field_class
*decl
= NULL
;
4649 * Just add the field class specifier to the root
4650 * declaration scope. Put local reference.
4652 ret
= visit_field_class_specifier_list(ctx
, root_decl_node
, &decl
);
4654 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4655 "Cannot visit root scope's field class: "
4661 ctf_field_class_destroy(decl
);
4666 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4667 "Unexpected node type: node-type=%d",
4668 root_decl_node
->type
);
4678 struct ctf_visitor_generate_ir
*ctf_visitor_generate_ir_create(
4679 const struct ctf_metadata_decoder_config
*decoder_config
)
4681 struct ctf_visitor_generate_ir
*ctx
= NULL
;
4683 /* Create visitor's context */
4684 ctx
= ctx_create(decoder_config
);
4686 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
,
4687 decoder_config
->self_comp
,
4688 "Cannot create visitor's context.");
4703 void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir
*visitor
)
4705 ctx_destroy(visitor
);
4709 bt_trace_class
*ctf_visitor_generate_ir_get_ir_trace_class(
4710 struct ctf_visitor_generate_ir
*ctx
)
4714 if (ctx
->trace_class
) {
4715 bt_trace_class_get_ref(ctx
->trace_class
);
4718 return ctx
->trace_class
;
4722 struct ctf_trace_class
*ctf_visitor_generate_ir_borrow_ctf_trace_class(
4723 struct ctf_visitor_generate_ir
*ctx
)
4726 BT_ASSERT_DBG(ctx
->ctf_tc
);
4731 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir
*ctx
,
4732 struct ctf_node
*node
)
4736 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
4738 switch (node
->type
) {
4741 struct ctf_node
*iter
;
4742 bool got_trace_decl
= false;
4745 * The first thing we need is the native byte order of
4746 * the trace block, because early class aliases can have
4747 * a `byte_order` attribute set to `native`. If we don't
4748 * have the native byte order yet, and we don't have any
4749 * trace block yet, then fail with EINCOMPLETE.
4751 if (ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
4752 bt_list_for_each_entry(iter
, &node
->u
.root
.trace
, siblings
) {
4753 if (got_trace_decl
) {
4754 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4755 "Duplicate trace (`trace` block).");
4760 ret
= set_trace_byte_order(ctx
, iter
);
4762 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4763 "Cannot set trace's native byte order: "
4768 got_trace_decl
= true;
4771 if (!got_trace_decl
) {
4772 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
4778 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_LITTLE
||
4779 ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_BIG
);
4780 BT_ASSERT(ctx
->current_scope
&&
4781 !ctx
->current_scope
->parent_scope
);
4784 bt_list_for_each_entry(iter
, &node
->u
.root
.env
, siblings
) {
4785 ret
= visit_env(ctx
, iter
);
4787 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4788 "Cannot visit trace's environment (`env` block) entry: "
4794 BT_ASSERT(ctx
->current_scope
&&
4795 !ctx
->current_scope
->parent_scope
);
4798 * Visit clock blocks.
4800 bt_list_for_each_entry(iter
, &node
->u
.root
.clock
, siblings
) {
4801 ret
= visit_clock_decl(ctx
, iter
);
4803 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4804 "Cannot visit clock class: ret=%d",
4810 BT_ASSERT(ctx
->current_scope
&&
4811 !ctx
->current_scope
->parent_scope
);
4814 * Visit root declarations next, as they can be used by any
4817 bt_list_for_each_entry(iter
, &node
->u
.root
.declaration_list
,
4819 ret
= visit_root_decl(ctx
, iter
);
4821 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4822 "Cannot visit root entry: ret=%d",
4828 BT_ASSERT(ctx
->current_scope
&&
4829 !ctx
->current_scope
->parent_scope
);
4831 /* Callsite blocks are not supported */
4832 bt_list_for_each_entry(iter
, &node
->u
.root
.callsite
, siblings
) {
4833 _BT_COMP_LOGW_NODE(iter
,
4834 "\"callsite\" blocks are not supported as of this version.");
4837 BT_ASSERT(ctx
->current_scope
&&
4838 !ctx
->current_scope
->parent_scope
);
4841 bt_list_for_each_entry(iter
, &node
->u
.root
.trace
, siblings
) {
4842 ret
= visit_trace_decl(ctx
, iter
);
4844 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4845 "Cannot visit trace (`trace` block): "
4851 BT_ASSERT(ctx
->current_scope
&&
4852 !ctx
->current_scope
->parent_scope
);
4855 bt_list_for_each_entry(iter
, &node
->u
.root
.stream
, siblings
) {
4856 ret
= visit_stream_decl(ctx
, iter
);
4858 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4859 "Cannot visit stream class: ret=%d",
4865 BT_ASSERT(ctx
->current_scope
&&
4866 !ctx
->current_scope
->parent_scope
);
4869 bt_list_for_each_entry(iter
, &node
->u
.root
.event
, siblings
) {
4870 ret
= visit_event_decl(ctx
, iter
);
4872 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4873 "Cannot visit event class: ret=%d",
4879 BT_ASSERT(ctx
->current_scope
&&
4880 !ctx
->current_scope
->parent_scope
);
4884 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4885 "Unexpected node type: node-type=%d",
4891 /* Update default clock classes */
4892 ret
= ctf_trace_class_update_default_clock_classes(ctx
->ctf_tc
,
4899 /* Update trace class meanings */
4900 ret
= ctf_trace_class_update_meanings(ctx
->ctf_tc
);
4906 /* Update stream class configuration */
4907 ret
= ctf_trace_class_update_stream_class_config(ctx
->ctf_tc
);
4913 /* Update text arrays and sequences */
4914 ret
= ctf_trace_class_update_text_array_sequence(ctx
->ctf_tc
);
4920 /* Update structure/array/sequence alignments */
4921 ret
= ctf_trace_class_update_alignments(ctx
->ctf_tc
);
4927 /* Resolve sequence lengths and variant tags */
4928 ret
= ctf_trace_class_resolve_field_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4934 if (ctx
->trace_class
) {
4936 * Update "in IR" for field classes.
4938 * If we have no IR trace class, then we'll have no way
4939 * to create IR fields anyway, so we leave all the
4940 * `in_ir` members false.
4942 ret
= ctf_trace_class_update_in_ir(ctx
->ctf_tc
);
4949 /* Update saved value indexes */
4950 ret
= ctf_trace_class_update_value_storing_indexes(ctx
->ctf_tc
);
4956 /* Validate what we have so far */
4957 ret
= ctf_trace_class_validate(ctx
->ctf_tc
, &ctx
->log_cfg
);
4964 * If there are fields which are not related to the CTF format
4965 * itself in the packet header and in event header field
4966 * classes, warn about it because they are never translated.
4968 ctf_trace_class_warn_meaningless_header_fields(ctx
->ctf_tc
,
4971 if (ctx
->trace_class
) {
4972 /* Copy new CTF metadata -> new IR metadata */
4973 ret
= ctf_trace_class_translate(ctx
->log_cfg
.self_comp
,
4974 ctx
->trace_class
, ctx
->ctf_tc
);