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"
27 #include "common/common.h"
28 #include "common/uuid.h"
29 #include "compat/endian.h"
30 #include <babeltrace2/babeltrace.h>
32 #include "logging.hpp"
33 #include "scanner.hpp"
35 #include "decoder.hpp"
36 #include "ctf-meta.hpp"
37 #include "ctf-meta-visitors.hpp"
39 /* Bit value (left shift) */
40 #define _BV(_val) (1 << (_val))
42 /* Bit is set in a set of bits */
43 #define _IS_SET(_set, _mask) (*(_set) & (_mask))
45 /* Set bit in a set of bits */
46 #define _SET(_set, _mask) (*(_set) |= (_mask))
48 /* Try to push scope, or go to the `error` label */
49 #define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
51 ret = ctx_push_scope(ctx); \
53 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot push scope."); \
58 /* Bits for verifying existing attributes in various declarations */
61 _CLOCK_NAME_SET
= _BV(0),
62 _CLOCK_UUID_SET
= _BV(1),
63 _CLOCK_FREQ_SET
= _BV(2),
64 _CLOCK_PRECISION_SET
= _BV(3),
65 _CLOCK_OFFSET_S_SET
= _BV(4),
66 _CLOCK_OFFSET_SET
= _BV(5),
67 _CLOCK_ABSOLUTE_SET
= _BV(6),
68 _CLOCK_DESCRIPTION_SET
= _BV(7),
73 _INTEGER_ALIGN_SET
= _BV(0),
74 _INTEGER_SIZE_SET
= _BV(1),
75 _INTEGER_BASE_SET
= _BV(2),
76 _INTEGER_ENCODING_SET
= _BV(3),
77 _INTEGER_BYTE_ORDER_SET
= _BV(4),
78 _INTEGER_SIGNED_SET
= _BV(5),
79 _INTEGER_MAP_SET
= _BV(6),
84 _FLOAT_ALIGN_SET
= _BV(0),
85 _FLOAT_MANT_DIG_SET
= _BV(1),
86 _FLOAT_EXP_DIG_SET
= _BV(2),
87 _FLOAT_BYTE_ORDER_SET
= _BV(3),
92 _STRING_ENCODING_SET
= _BV(0),
97 _TRACE_MINOR_SET
= _BV(0),
98 _TRACE_MAJOR_SET
= _BV(1),
99 _TRACE_BYTE_ORDER_SET
= _BV(2),
100 _TRACE_UUID_SET
= _BV(3),
101 _TRACE_PACKET_HEADER_SET
= _BV(4),
106 _STREAM_ID_SET
= _BV(0),
107 _STREAM_PACKET_CONTEXT_SET
= _BV(1),
108 _STREAM_EVENT_HEADER_SET
= _BV(2),
109 _STREAM_EVENT_CONTEXT_SET
= _BV(3),
114 _EVENT_NAME_SET
= _BV(0),
115 _EVENT_ID_SET
= _BV(1),
116 _EVENT_MODEL_EMF_URI_SET
= _BV(2),
117 _EVENT_STREAM_ID_SET
= _BV(3),
118 _EVENT_LOG_LEVEL_SET
= _BV(4),
119 _EVENT_CONTEXT_SET
= _BV(5),
120 _EVENT_FIELDS_SET
= _BV(6),
129 LOG_LEVEL_WARNING
= 4,
130 LOG_LEVEL_NOTICE
= 5,
132 LOG_LEVEL_DEBUG_SYSTEM
= 7,
133 LOG_LEVEL_DEBUG_PROGRAM
= 8,
134 LOG_LEVEL_DEBUG_PROCESS
= 9,
135 LOG_LEVEL_DEBUG_MODULE
= 10,
136 LOG_LEVEL_DEBUG_UNIT
= 11,
137 LOG_LEVEL_DEBUG_FUNCTION
= 12,
138 LOG_LEVEL_DEBUG_LINE
= 13,
139 LOG_LEVEL_DEBUG
= 14,
143 /* Prefixes of class aliases */
144 #define _PREFIX_ALIAS 'a'
145 #define _PREFIX_ENUM 'e'
146 #define _PREFIX_STRUCT 's'
147 #define _PREFIX_VARIANT 'v'
149 /* First entry in a BT list */
150 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) bt_list_entry((_ptr)->next, _class, _member)
152 #define _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \
153 _BT_COMP_LOGE_APPEND_CAUSE_LINENO( \
154 (_node)->lineno, "Duplicate attribute in %s: attr-name=\"%s\"", _entity, _attr)
156 #define _BT_COMP_LOGE_NODE(_node, _msg, args...) _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ##args)
158 #define _BT_COMP_LOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
159 _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, _msg, ##args)
161 #define _BT_COMP_LOGW_NODE(_node, _msg, args...) _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ##args)
163 #define _BT_COMP_LOGT_NODE(_node, _msg, args...) _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ##args)
166 * Declaration scope of a visitor context. This represents a TSDL
167 * lexical scope, so that aliases and named structures, variants,
168 * and enumerations may be registered and looked up hierarchically.
170 struct ctx_decl_scope
173 * Alias name to field class.
175 * GQuark -> struct ctf_field_class * (owned by this)
177 GHashTable
*decl_map
;
179 /* Parent scope; NULL if this is the root declaration scope */
180 struct ctx_decl_scope
*parent_scope
;
184 * Visitor context (private).
186 struct ctf_visitor_generate_ir
188 struct meta_log_config log_cfg
;
190 /* Trace IR trace class being filled (owned by this) */
191 bt_trace_class
*trace_class
;
193 /* CTF meta trace being filled (owned by this) */
194 struct ctf_trace_class
*ctf_tc
;
196 /* Current declaration scope (top of the stack) (owned by this) */
197 struct ctx_decl_scope
*current_scope
;
199 /* True if trace declaration is visited */
200 bool is_trace_visited
;
202 /* True if this is an LTTng trace */
205 /* Config passed by the user */
206 struct ctf_metadata_decoder_config decoder_config
;
212 struct ctf_visitor_generate_ir
;
215 * Creates a new declaration scope.
217 * @param par_scope Parent scope (NULL if creating a root scope)
218 * @returns New declaration scope, or NULL on error
220 static struct ctx_decl_scope
*ctx_decl_scope_create(struct ctf_visitor_generate_ir
*ctx
,
221 struct ctx_decl_scope
*par_scope
)
223 struct ctx_decl_scope
*scope
;
225 scope
= g_new(struct ctx_decl_scope
, 1);
227 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate one declaration scope.");
231 scope
->decl_map
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
,
232 (GDestroyNotify
) ctf_field_class_destroy
);
233 scope
->parent_scope
= par_scope
;
240 * Destroys a declaration scope.
242 * This function does not destroy the parent scope.
244 * @param scope Scope to destroy
246 static void ctx_decl_scope_destroy(struct ctx_decl_scope
*scope
)
252 g_hash_table_destroy(scope
->decl_map
);
260 * Returns the GQuark of a prefixed alias.
262 * @param prefix Prefix character
264 * @returns Associated GQuark, or 0 on error
266 static GQuark
get_prefixed_named_quark(char prefix
, const char *name
)
269 std::string prname
= std::string
{prefix
} + name
;
270 return g_quark_from_string(prname
.c_str());
274 * Looks up a prefixed class alias within a declaration scope.
276 * @param scope Declaration scope
277 * @param prefix Prefix character
278 * @param name Alias name
279 * @param levels Number of levels to dig into (-1 means infinite)
280 * @param copy True to return a copy
281 * @returns Declaration (owned by caller if \p copy is true),
282 * or NULL if not found
284 static struct ctf_field_class
*ctx_decl_scope_lookup_prefix_alias(struct ctx_decl_scope
*scope
,
285 char prefix
, const char *name
,
286 int levels
, bool copy
)
290 struct ctf_field_class
*decl
= NULL
;
291 struct ctx_decl_scope
*cur_scope
= scope
;
295 qname
= get_prefixed_named_quark(prefix
, name
);
304 while (cur_scope
&& cur_levels
< levels
) {
305 decl
= (ctf_field_class
*) g_hash_table_lookup(cur_scope
->decl_map
,
306 (gconstpointer
) GUINT_TO_POINTER(qname
));
308 /* Caller's reference */
310 decl
= ctf_field_class_copy(decl
);
317 cur_scope
= cur_scope
->parent_scope
;
326 * Looks up a class alias within a declaration scope.
328 * @param scope Declaration scope
329 * @param name Alias name
330 * @param levels Number of levels to dig into (-1 means infinite)
331 * @param copy True to return a copy
332 * @returns Declaration (owned by caller if \p copy is true),
333 * or NULL if not found
335 static struct ctf_field_class
*ctx_decl_scope_lookup_alias(struct ctx_decl_scope
*scope
,
336 const char *name
, int levels
, bool copy
)
338 return ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ALIAS
, name
, levels
, copy
);
342 * Looks up an enumeration within a declaration scope.
344 * @param scope Declaration scope
345 * @param name Enumeration name
346 * @param levels Number of levels to dig into (-1 means infinite)
347 * @param copy True to return a copy
348 * @returns Declaration (owned by caller if \p copy is true),
349 * or NULL if not found
351 static struct ctf_field_class_enum
*
352 ctx_decl_scope_lookup_enum(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
354 return ctf_field_class_as_enum(
355 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ENUM
, name
, levels
, copy
));
359 * Looks up a structure within a declaration scope.
361 * @param scope Declaration scope
362 * @param name Structure name
363 * @param levels Number of levels to dig into (-1 means infinite)
364 * @param copy True to return a copy
365 * @returns Declaration (owned by caller if \p copy is true),
366 * or NULL if not found
368 static struct ctf_field_class_struct
*
369 ctx_decl_scope_lookup_struct(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
371 return ctf_field_class_as_struct(
372 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_STRUCT
, name
, levels
, copy
));
376 * Looks up a variant within a declaration scope.
378 * @param scope Declaration scope
379 * @param name Variant name
380 * @param levels Number of levels to dig into (-1 means infinite)
381 * @param copy True to return a copy
382 * @returns Declaration (owned by caller if \p copy is true),
383 * or NULL if not found
385 static struct ctf_field_class_variant
*
386 ctx_decl_scope_lookup_variant(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
388 return ctf_field_class_as_variant(
389 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_VARIANT
, name
, levels
, copy
));
393 * Registers a prefixed class alias within a declaration scope.
395 * @param scope Declaration scope
396 * @param prefix Prefix character
397 * @param name Alias name (non-NULL)
398 * @param decl Field class to register (copied)
399 * @returns 0 if registration went okay, negative value otherwise
401 static int ctx_decl_scope_register_prefix_alias(struct ctx_decl_scope
*scope
, char prefix
,
402 const char *name
, struct ctf_field_class
*decl
)
410 qname
= get_prefixed_named_quark(prefix
, name
);
416 /* Make sure alias does not exist in local scope */
417 if (ctx_decl_scope_lookup_prefix_alias(scope
, prefix
, name
, 1, false)) {
422 decl
= ctf_field_class_copy(decl
);
424 g_hash_table_insert(scope
->decl_map
, GUINT_TO_POINTER(qname
), decl
);
431 * Registers a class alias within a declaration scope.
433 * @param scope Declaration scope
434 * @param name Alias name (non-NULL)
435 * @param decl Field class to register (copied)
436 * @returns 0 if registration went okay, negative value otherwise
438 static int ctx_decl_scope_register_alias(struct ctx_decl_scope
*scope
, const char *name
,
439 struct ctf_field_class
*decl
)
441 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ALIAS
, name
, decl
);
445 * Registers an enumeration declaration within a declaration scope.
447 * @param scope Declaration scope
448 * @param name Enumeration name (non-NULL)
449 * @param decl Enumeration field class to register (copied)
450 * @returns 0 if registration went okay, negative value otherwise
452 static int ctx_decl_scope_register_enum(struct ctx_decl_scope
*scope
, const char *name
,
453 struct ctf_field_class_enum
*decl
)
455 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ENUM
, name
, &decl
->base
.base
.base
);
459 * Registers a structure declaration within a declaration scope.
461 * @param scope Declaration scope
462 * @param name Structure name (non-NULL)
463 * @param decl Structure field class to register (copied)
464 * @returns 0 if registration went okay, negative value otherwise
466 static int ctx_decl_scope_register_struct(struct ctx_decl_scope
*scope
, const char *name
,
467 struct ctf_field_class_struct
*decl
)
469 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_STRUCT
, name
, &decl
->base
);
473 * Registers a variant declaration within a declaration scope.
475 * @param scope Declaration scope
476 * @param name Variant name (non-NULL)
477 * @param decl Variant field class to register
478 * @returns 0 if registration went okay, negative value otherwise
480 static int ctx_decl_scope_register_variant(struct ctx_decl_scope
*scope
, const char *name
,
481 struct ctf_field_class_variant
*decl
)
483 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_VARIANT
, name
, &decl
->base
);
487 * Destroys a visitor context.
489 * @param ctx Visitor context to destroy
491 static void ctx_destroy(struct ctf_visitor_generate_ir
*ctx
)
493 struct ctx_decl_scope
*scope
;
499 scope
= ctx
->current_scope
;
502 * Destroy all scopes, from current one to the root scope.
505 struct ctx_decl_scope
*parent_scope
= scope
->parent_scope
;
507 ctx_decl_scope_destroy(scope
);
508 scope
= parent_scope
;
511 bt_trace_class_put_ref(ctx
->trace_class
);
514 ctf_trace_class_destroy(ctx
->ctf_tc
);
524 * Creates a new visitor context.
526 * @param trace Associated trace
527 * @returns New visitor context, or NULL on error
529 static struct ctf_visitor_generate_ir
*
530 ctx_create(const struct ctf_metadata_decoder_config
*decoder_config
)
532 struct ctf_visitor_generate_ir
*ctx
= NULL
;
534 BT_ASSERT(decoder_config
);
536 ctx
= g_new0(struct ctf_visitor_generate_ir
, 1);
538 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
, decoder_config
->self_comp
,
539 "Failed to allocate one visitor context.");
543 ctx
->log_cfg
.log_level
= decoder_config
->log_level
;
544 ctx
->log_cfg
.self_comp
= decoder_config
->self_comp
;
545 ctx
->log_cfg
.self_comp_class
= decoder_config
->self_comp_class
;
547 if (decoder_config
->self_comp
) {
548 ctx
->trace_class
= bt_trace_class_create(decoder_config
->self_comp
);
549 if (!ctx
->trace_class
) {
550 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create empty trace class.");
555 ctx
->ctf_tc
= ctf_trace_class_create();
557 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create CTF trace class.");
561 /* Root declaration scope */
562 ctx
->current_scope
= ctx_decl_scope_create(ctx
, NULL
);
563 if (!ctx
->current_scope
) {
564 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
568 ctx
->decoder_config
= *decoder_config
;
580 * Pushes a new declaration scope on top of a visitor context's
581 * declaration scope stack.
583 * @param ctx Visitor context
584 * @returns 0 on success, or a negative value on error
586 static int ctx_push_scope(struct ctf_visitor_generate_ir
*ctx
)
589 struct ctx_decl_scope
*new_scope
;
592 new_scope
= ctx_decl_scope_create(ctx
, ctx
->current_scope
);
594 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
599 ctx
->current_scope
= new_scope
;
605 static void ctx_pop_scope(struct ctf_visitor_generate_ir
*ctx
)
607 struct ctx_decl_scope
*parent_scope
= NULL
;
611 if (!ctx
->current_scope
) {
615 parent_scope
= ctx
->current_scope
->parent_scope
;
616 ctx_decl_scope_destroy(ctx
->current_scope
);
617 ctx
->current_scope
= parent_scope
;
623 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
624 struct ctf_node
*ts_list
,
625 struct ctf_field_class
**decl
);
627 static int is_unary_string(struct bt_list_head
*head
)
630 struct ctf_node
*node
;
632 bt_list_for_each_entry (node
, head
, siblings
) {
633 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
637 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
645 static const char *get_map_clock_name_value(struct bt_list_head
*head
)
648 struct ctf_node
*node
;
649 const char *name
= NULL
;
651 bt_list_for_each_entry (node
, head
, siblings
) {
653 int uexpr_type
= node
->u
.unary_expression
.type
;
654 int uexpr_link
= node
->u
.unary_expression
.link
;
655 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_STRING
||
656 !((uexpr_link
!= UNARY_LINK_UNKNOWN
) ^ (i
== 0));
661 /* Needs to be chained with . */
662 switch (node
->u
.unary_expression
.link
) {
665 case UNARY_ARROWLINK
:
666 case UNARY_DOTDOTDOT
:
672 src_string
= node
->u
.unary_expression
.u
.string
;
676 if (strcmp("clock", src_string
)) {
684 if (strcmp("value", src_string
)) {
689 /* Extra identifier, unknown */
702 static int is_unary_unsigned(struct bt_list_head
*head
)
705 struct ctf_node
*node
;
707 bt_list_for_each_entry (node
, head
, siblings
) {
708 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
712 if (node
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
720 static int get_unary_unsigned(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
725 struct ctf_node
*node
;
729 if (bt_list_empty(head
)) {
734 bt_list_for_each_entry (node
, head
, siblings
) {
735 int uexpr_type
= node
->u
.unary_expression
.type
;
736 int uexpr_link
= node
->u
.unary_expression
.link
;
737 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_UNSIGNED_CONSTANT
||
738 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
740 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid constant unsigned integer.");
745 *value
= node
->u
.unary_expression
.u
.unsigned_constant
;
753 static int is_unary_signed(struct bt_list_head
*head
)
756 struct ctf_node
*node
;
758 bt_list_for_each_entry (node
, head
, siblings
) {
759 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
763 if (node
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
) {
771 static int get_unary_signed(struct bt_list_head
*head
, int64_t *value
)
775 struct ctf_node
*node
;
777 bt_list_for_each_entry (node
, head
, siblings
) {
778 int uexpr_type
= node
->u
.unary_expression
.type
;
779 int uexpr_link
= node
->u
.unary_expression
.link
;
780 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
781 (uexpr_type
!= UNARY_UNSIGNED_CONSTANT
&& uexpr_type
!= UNARY_SIGNED_CONSTANT
) ||
782 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
788 switch (uexpr_type
) {
789 case UNARY_UNSIGNED_CONSTANT
:
790 *value
= (int64_t) node
->u
.unary_expression
.u
.unsigned_constant
;
792 case UNARY_SIGNED_CONSTANT
:
793 *value
= node
->u
.unary_expression
.u
.signed_constant
;
807 static int get_unary_uuid(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
810 return ctf_ast_get_unary_uuid(head
, uuid
, ctx
->log_cfg
.log_level
, ctx
->log_cfg
.self_comp
);
813 static int get_boolean(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*unary_expr
)
817 if (unary_expr
->type
!= NODE_UNARY_EXPRESSION
) {
818 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
, "Expecting unary expression: node-type=%d",
824 switch (unary_expr
->u
.unary_expression
.type
) {
825 case UNARY_UNSIGNED_CONSTANT
:
826 ret
= (unary_expr
->u
.unary_expression
.u
.unsigned_constant
!= 0);
828 case UNARY_SIGNED_CONSTANT
:
829 ret
= (unary_expr
->u
.unary_expression
.u
.signed_constant
!= 0);
833 const char *str
= unary_expr
->u
.unary_expression
.u
.string
;
835 if (strcmp(str
, "true") == 0 || strcmp(str
, "TRUE") == 0) {
837 } else if (strcmp(str
, "false") == 0 || strcmp(str
, "FALSE") == 0) {
840 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
, "Unexpected boolean value: value=\"%s\"",
848 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
849 "Unexpected unary expression type: node-type=%d",
850 unary_expr
->u
.unary_expression
.type
);
859 static enum ctf_byte_order
byte_order_from_unary_expr(struct ctf_visitor_generate_ir
*ctx
,
860 struct ctf_node
*unary_expr
)
863 enum ctf_byte_order bo
= CTF_BYTE_ORDER_UNKNOWN
;
865 if (unary_expr
->u
.unary_expression
.type
!= UNARY_STRING
) {
866 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
867 unary_expr
, "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
871 str
= unary_expr
->u
.unary_expression
.u
.string
;
873 if (strcmp(str
, "be") == 0 || strcmp(str
, "network") == 0) {
874 bo
= CTF_BYTE_ORDER_BIG
;
875 } else if (strcmp(str
, "le") == 0) {
876 bo
= CTF_BYTE_ORDER_LITTLE
;
877 } else if (strcmp(str
, "native") == 0) {
878 bo
= CTF_BYTE_ORDER_DEFAULT
;
880 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
882 "Unexpected \"byte_order\" attribute value: "
883 "expecting `be`, `le`, `network`, or `native`: value=\"%s\"",
892 static enum ctf_byte_order
get_real_byte_order(struct ctf_visitor_generate_ir
*ctx
,
893 struct ctf_node
*uexpr
)
895 enum ctf_byte_order bo
= byte_order_from_unary_expr(ctx
, uexpr
);
897 if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
898 bo
= ctx
->ctf_tc
->default_byte_order
;
904 static int is_align_valid(uint64_t align
)
906 return (align
!= 0) && !(align
& (align
- UINT64_C(1)));
909 static int get_class_specifier_name(struct ctf_visitor_generate_ir
*ctx
,
910 struct ctf_node
*cls_specifier
, GString
*str
)
914 if (cls_specifier
->type
!= NODE_TYPE_SPECIFIER
) {
915 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
, "Unexpected node type: node-type=%d",
916 cls_specifier
->type
);
921 switch (cls_specifier
->u
.field_class_specifier
.type
) {
923 g_string_append(str
, "void");
926 g_string_append(str
, "char");
929 g_string_append(str
, "short");
932 g_string_append(str
, "int");
935 g_string_append(str
, "long");
938 g_string_append(str
, "float");
940 case TYPESPEC_DOUBLE
:
941 g_string_append(str
, "double");
943 case TYPESPEC_SIGNED
:
944 g_string_append(str
, "signed");
946 case TYPESPEC_UNSIGNED
:
947 g_string_append(str
, "unsigned");
950 g_string_append(str
, "bool");
952 case TYPESPEC_COMPLEX
:
953 g_string_append(str
, "_Complex");
955 case TYPESPEC_IMAGINARY
:
956 g_string_append(str
, "_Imaginary");
959 g_string_append(str
, "const");
961 case TYPESPEC_ID_TYPE
:
962 if (cls_specifier
->u
.field_class_specifier
.id_type
) {
963 g_string_append(str
, cls_specifier
->u
.field_class_specifier
.id_type
);
966 case TYPESPEC_STRUCT
:
968 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
970 if (!node
->u
._struct
.name
) {
971 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty structure field class name.");
976 g_string_append(str
, "struct ");
977 g_string_append(str
, node
->u
._struct
.name
);
980 case TYPESPEC_VARIANT
:
982 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
984 if (!node
->u
.variant
.name
) {
985 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty variant field class name.");
990 g_string_append(str
, "variant ");
991 g_string_append(str
, node
->u
.variant
.name
);
996 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
998 if (!node
->u
._enum
.enum_id
) {
999 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1000 node
, "Unexpected empty enumeration field class (`enum`) name.");
1005 g_string_append(str
, "enum ");
1006 g_string_append(str
, node
->u
._enum
.enum_id
);
1009 case TYPESPEC_FLOATING_POINT
:
1010 case TYPESPEC_INTEGER
:
1011 case TYPESPEC_STRING
:
1013 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
->u
.field_class_specifier
.node
,
1014 "Unexpected field class specifier type: %d",
1015 cls_specifier
->u
.field_class_specifier
.type
);
1024 static int get_class_specifier_list_name(struct ctf_visitor_generate_ir
*ctx
,
1025 struct ctf_node
*cls_specifier_list
, GString
*str
)
1028 struct ctf_node
*iter
;
1029 int alias_item_nr
= 0;
1030 struct bt_list_head
*head
= &cls_specifier_list
->u
.field_class_specifier_list
.head
;
1032 bt_list_for_each_entry (iter
, head
, siblings
) {
1033 if (alias_item_nr
!= 0) {
1034 g_string_append(str
, " ");
1038 ret
= get_class_specifier_name(ctx
, iter
, str
);
1048 static GQuark
create_class_alias_identifier(struct ctf_visitor_generate_ir
*ctx
,
1049 struct ctf_node
*cls_specifier_list
,
1050 struct ctf_node
*node_field_class_declarator
)
1056 struct ctf_node
*iter
;
1057 struct bt_list_head
*pointers
= &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1059 str
= g_string_new("");
1060 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
1062 g_string_free(str
, TRUE
);
1066 bt_list_for_each_entry (iter
, pointers
, siblings
) {
1067 g_string_append(str
, " *");
1069 if (iter
->u
.pointer
.const_qualifier
) {
1070 g_string_append(str
, " const");
1074 str_c
= g_string_free(str
, FALSE
);
1075 qalias
= g_quark_from_string(str_c
);
1082 static int visit_field_class_declarator(struct ctf_visitor_generate_ir
*ctx
,
1083 struct ctf_node
*cls_specifier_list
, GQuark
*field_name
,
1084 struct ctf_node
*node_field_class_declarator
,
1085 struct ctf_field_class
**field_decl
,
1086 struct ctf_field_class
*nested_decl
)
1089 * During this whole function, nested_decl is always OURS,
1090 * whereas field_decl is an output which we create, but
1091 * belongs to the caller (it is moved).
1096 /* Validate field class declarator node */
1097 if (node_field_class_declarator
) {
1098 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_UNKNOWN
) {
1099 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1100 node_field_class_declarator
, "Unexpected field class declarator type: type=%d",
1101 node_field_class_declarator
->u
.field_class_declarator
.type
);
1106 /* TODO: GCC bitfields not supported yet */
1107 if (node_field_class_declarator
->u
.field_class_declarator
.bitfield_len
!= NULL
) {
1108 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1109 "GCC bitfields are not supported as of this version.");
1115 /* Find the right nested declaration if not provided */
1117 if (node_field_class_declarator
&&
1118 !bt_list_empty(&node_field_class_declarator
->u
.field_class_declarator
.pointers
)) {
1122 * If we have a pointer declarator, it HAS to
1123 * be present in the field class aliases (else
1127 create_class_alias_identifier(ctx
, cls_specifier_list
, node_field_class_declarator
);
1128 nested_decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, g_quark_to_string(qalias
),
1131 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1132 "Cannot find class alias: name=\"%s\"",
1133 g_quark_to_string(qalias
));
1138 if (nested_decl
->type
== CTF_FIELD_CLASS_TYPE_INT
) {
1139 /* Pointer: force integer's base to 16 */
1140 struct ctf_field_class_int
*int_fc
= ctf_field_class_as_int(nested_decl
);
1142 int_fc
->disp_base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
1145 ret
= visit_field_class_specifier_list(ctx
, cls_specifier_list
, &nested_decl
);
1147 BT_ASSERT(!nested_decl
);
1153 BT_ASSERT(nested_decl
);
1155 if (!node_field_class_declarator
) {
1156 *field_decl
= nested_decl
;
1161 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_ID
) {
1162 if (node_field_class_declarator
->u
.field_class_declarator
.u
.id
) {
1163 const char *id
= node_field_class_declarator
->u
.field_class_declarator
.u
.id
;
1165 *field_name
= g_quark_from_string(id
);
1170 *field_decl
= nested_decl
;
1174 struct ctf_node
*first
;
1175 struct ctf_field_class
*decl
= NULL
;
1176 struct ctf_field_class
*outer_field_decl
= NULL
;
1177 struct bt_list_head
*length
=
1178 &node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.length
;
1180 /* Create array/sequence, pass nested_decl as child */
1181 if (bt_list_empty(length
)) {
1182 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1183 "Expecting length field reference or value.");
1188 first
= _BT_LIST_FIRST_ENTRY(length
, struct ctf_node
, siblings
);
1189 if (first
->type
!= NODE_UNARY_EXPRESSION
) {
1190 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type=%d",
1196 switch (first
->u
.unary_expression
.type
) {
1197 case UNARY_UNSIGNED_CONSTANT
:
1199 struct ctf_field_class_array
*array_decl
= NULL
;
1201 array_decl
= ctf_field_class_array_create();
1202 BT_ASSERT(array_decl
);
1203 array_decl
->length
= first
->u
.unary_expression
.u
.unsigned_constant
;
1204 array_decl
->base
.elem_fc
= nested_decl
;
1206 decl
= &array_decl
->base
.base
;
1211 /* Lookup unsigned integer definition, create seq. */
1212 struct ctf_field_class_sequence
*seq_decl
= NULL
;
1213 char *length_name
= ctf_ast_concatenate_unary_strings(length
);
1216 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1217 "Cannot concatenate unary strings.");
1222 if (strncmp(length_name
, "env.", 4) == 0) {
1223 /* This is, in fact, an array */
1224 const char *env_entry_name
= &length_name
[4];
1225 struct ctf_trace_class_env_entry
*env_entry
=
1226 ctf_trace_class_borrow_env_entry_by_name(ctx
->ctf_tc
, env_entry_name
);
1227 struct ctf_field_class_array
*array_decl
;
1230 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1231 "Cannot find environment entry: "
1238 if (env_entry
->type
!= CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
) {
1239 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1240 "Wrong environment entry type "
1241 "(expecting integer): "
1248 if (env_entry
->value
.i
< 0) {
1249 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1250 "Invalid, negative array length: "
1251 "env-entry-name=\"%s\", "
1253 env_entry_name
, env_entry
->value
.i
);
1258 array_decl
= ctf_field_class_array_create();
1259 BT_ASSERT(array_decl
);
1260 array_decl
->length
= (uint64_t) env_entry
->value
.i
;
1261 array_decl
->base
.elem_fc
= nested_decl
;
1263 decl
= &array_decl
->base
.base
;
1265 seq_decl
= ctf_field_class_sequence_create();
1266 BT_ASSERT(seq_decl
);
1267 seq_decl
->base
.elem_fc
= nested_decl
;
1269 g_string_assign(seq_decl
->length_ref
, length_name
);
1270 decl
= &seq_decl
->base
.base
;
1273 g_free(length_name
);
1281 BT_ASSERT(!nested_decl
);
1283 BT_ASSERT(!*field_decl
);
1286 * At this point, we found the next nested declaration.
1287 * We currently own this (and lost the ownership of
1288 * nested_decl in the meantime). Pass this next
1289 * nested declaration as the content of the outer
1290 * container, MOVING its ownership.
1292 ret
= visit_field_class_declarator(
1293 ctx
, cls_specifier_list
, field_name
,
1294 node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.field_class_declarator
,
1295 &outer_field_decl
, decl
);
1298 BT_ASSERT(!outer_field_decl
);
1303 BT_ASSERT(outer_field_decl
);
1304 *field_decl
= outer_field_decl
;
1305 outer_field_decl
= NULL
;
1308 BT_ASSERT(*field_decl
);
1312 ctf_field_class_destroy(*field_decl
);
1320 ctf_field_class_destroy(nested_decl
);
1325 static int visit_struct_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1326 struct ctf_field_class_struct
*struct_decl
,
1327 struct ctf_node
*cls_specifier_list
,
1328 struct bt_list_head
*field_class_declarators
)
1331 struct ctf_node
*iter
;
1332 struct ctf_field_class
*field_decl
= NULL
;
1334 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1337 const char *field_name
;
1339 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1342 BT_ASSERT(!field_decl
);
1343 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1344 "Cannot visit field class declarator: ret=%d", ret
);
1348 BT_ASSERT(field_decl
);
1349 field_name
= g_quark_to_string(qfield_name
);
1351 /* Check if field with same name already exists */
1352 if (ctf_field_class_struct_borrow_member_by_name(struct_decl
, field_name
)) {
1353 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1354 "Duplicate field in structure field class: "
1355 "field-name=\"%s\"",
1361 /* Add field to structure */
1362 ctf_field_class_struct_append_member(struct_decl
, field_name
, field_decl
);
1369 ctf_field_class_destroy(field_decl
);
1374 static int visit_variant_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1375 struct ctf_field_class_variant
*variant_decl
,
1376 struct ctf_node
*cls_specifier_list
,
1377 struct bt_list_head
*field_class_declarators
)
1380 struct ctf_node
*iter
;
1381 struct ctf_field_class
*field_decl
= NULL
;
1383 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1386 const char *field_name
;
1388 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1391 BT_ASSERT(!field_decl
);
1392 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1393 "Cannot visit field class declarator: ret=%d", ret
);
1397 BT_ASSERT(field_decl
);
1398 field_name
= g_quark_to_string(qfield_name
);
1400 /* Check if field with same name already exists */
1401 if (ctf_field_class_variant_borrow_option_by_name(variant_decl
, field_name
)) {
1402 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1403 "Duplicate field in variant field class: "
1404 "field-name=\"%s\"",
1410 /* Add field to structure */
1411 ctf_field_class_variant_append_option(variant_decl
, field_name
, field_decl
);
1418 ctf_field_class_destroy(field_decl
);
1423 static int visit_field_class_def(struct ctf_visitor_generate_ir
*ctx
,
1424 struct ctf_node
*cls_specifier_list
,
1425 struct bt_list_head
*field_class_declarators
)
1429 struct ctf_node
*iter
;
1430 struct ctf_field_class
*class_decl
= NULL
;
1432 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1433 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qidentifier
, iter
, &class_decl
,
1436 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit field class declarator: ret=%d",
1442 /* Do not allow field class def and alias of untagged variants */
1443 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1444 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1446 if (var_fc
->tag_path
.path
->len
== 0) {
1447 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1448 iter
, "Type definition of untagged variant field class is not allowed.");
1454 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qidentifier
),
1457 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot register field class alias: name=\"%s\"",
1458 g_quark_to_string(qidentifier
));
1464 ctf_field_class_destroy(class_decl
);
1469 static int visit_field_class_alias(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*target
,
1470 struct ctf_node
*alias
)
1474 struct ctf_node
*node
;
1475 GQuark qdummy_field_name
;
1476 struct ctf_field_class
*class_decl
= NULL
;
1478 /* Create target field class */
1479 if (bt_list_empty(&target
->u
.field_class_alias_target
.field_class_declarators
)) {
1482 node
= _BT_LIST_FIRST_ENTRY(&target
->u
.field_class_alias_target
.field_class_declarators
,
1483 struct ctf_node
, siblings
);
1486 ret
= visit_field_class_declarator(
1487 ctx
, target
->u
.field_class_alias_target
.field_class_specifier_list
, &qdummy_field_name
,
1488 node
, &class_decl
, NULL
);
1490 BT_ASSERT(!class_decl
);
1491 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot visit field class declarator: ret=%d", ret
);
1495 /* Do not allow field class def and alias of untagged variants */
1496 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1497 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1499 if (var_fc
->tag_path
.path
->len
== 0) {
1500 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1501 target
, "Type definition of untagged variant field class is not allowed.");
1508 * The semantic validator does not check whether the target is
1509 * abstract or not (if it has an identifier). Check it here.
1511 if (qdummy_field_name
!= 0) {
1512 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target
, "Expecting empty identifier: id=\"%s\"",
1513 g_quark_to_string(qdummy_field_name
));
1518 /* Create alias identifier */
1519 node
= _BT_LIST_FIRST_ENTRY(&alias
->u
.field_class_alias_name
.field_class_declarators
,
1520 struct ctf_node
, siblings
);
1521 qalias
= create_class_alias_identifier(
1522 ctx
, alias
->u
.field_class_alias_name
.field_class_specifier_list
, node
);
1523 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qalias
), class_decl
);
1525 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot register class alias: name=\"%s\"",
1526 g_quark_to_string(qalias
));
1531 ctf_field_class_destroy(class_decl
);
1536 static int visit_struct_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
1537 struct ctf_field_class_struct
*struct_decl
)
1541 switch (entry_node
->type
) {
1543 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1544 &entry_node
->u
.field_class_def
.field_class_declarators
);
1546 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1547 entry_node
, "Cannot add field class found in structure field class: ret=%d", ret
);
1551 case NODE_TYPEALIAS
:
1552 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1553 entry_node
->u
.field_class_alias
.alias
);
1555 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1556 entry_node
, "Cannot add field class alias found in structure field class: ret=%d",
1561 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1563 ret
= visit_struct_decl_field(
1565 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1566 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1572 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
1582 static int visit_variant_decl_entry(struct ctf_visitor_generate_ir
*ctx
,
1583 struct ctf_node
*entry_node
,
1584 struct ctf_field_class_variant
*variant_decl
)
1588 switch (entry_node
->type
) {
1590 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1591 &entry_node
->u
.field_class_def
.field_class_declarators
);
1593 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1594 entry_node
, "Cannot add field class found in variant field class: ret=%d", ret
);
1598 case NODE_TYPEALIAS
:
1599 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1600 entry_node
->u
.field_class_alias
.alias
);
1602 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1603 entry_node
, "Cannot add field class alias found in variant field class: ret=%d",
1608 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1610 ret
= visit_variant_decl_field(
1612 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1613 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1619 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
1629 static int visit_struct_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1630 struct bt_list_head
*decl_list
, int has_body
,
1631 struct bt_list_head
*min_align
,
1632 struct ctf_field_class_struct
**struct_decl
)
1636 BT_ASSERT(struct_decl
);
1637 *struct_decl
= NULL
;
1639 /* For named struct (without body), lookup in declaration scope */
1642 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1643 "Bodyless structure field class: missing name.");
1648 *struct_decl
= ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, -1, true);
1649 if (!*struct_decl
) {
1650 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1651 "Cannot find structure field class: name=\"struct %s\"", name
);
1656 struct ctf_node
*entry_node
;
1657 uint64_t min_align_value
= 0;
1660 if (ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, 1, false)) {
1661 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1662 "Structure field class already declared in local scope: "
1663 "name=\"struct %s\"",
1670 if (!bt_list_empty(min_align
)) {
1671 ret
= get_unary_unsigned(ctx
, min_align
, &min_align_value
);
1673 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1674 "Unexpected unary expression for structure field class's `align` attribute: "
1681 *struct_decl
= ctf_field_class_struct_create();
1682 BT_ASSERT(*struct_decl
);
1684 if (min_align_value
!= 0) {
1685 (*struct_decl
)->base
.alignment
= min_align_value
;
1688 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1690 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1691 ret
= visit_struct_decl_entry(ctx
, entry_node
, *struct_decl
);
1693 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1694 "Cannot visit structure field class entry: "
1705 ret
= ctx_decl_scope_register_struct(ctx
->current_scope
, name
, *struct_decl
);
1707 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1708 "Cannot register structure field class in declaration scope: "
1709 "name=\"struct %s\", ret=%d",
1719 ctf_field_class_destroy(&(*struct_decl
)->base
);
1720 *struct_decl
= NULL
;
1724 static int visit_variant_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1725 const char *tag
, struct bt_list_head
*decl_list
, int has_body
,
1726 struct ctf_field_class_variant
**variant_decl
)
1729 struct ctf_field_class_variant
*untagged_variant_decl
= NULL
;
1731 BT_ASSERT(variant_decl
);
1732 *variant_decl
= NULL
;
1734 /* For named variant (without body), lookup in declaration scope */
1737 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name.");
1742 untagged_variant_decl
= ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, -1, true);
1743 if (!untagged_variant_decl
) {
1744 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1745 "Cannot find variant field class: name=\"variant %s\"", name
);
1750 struct ctf_node
*entry_node
;
1753 if (ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, 1, false)) {
1754 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1755 "Variant field class already declared in local scope: "
1756 "name=\"variant %s\"",
1763 untagged_variant_decl
= ctf_field_class_variant_create();
1764 BT_ASSERT(untagged_variant_decl
);
1765 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1767 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1768 ret
= visit_variant_decl_entry(ctx
, entry_node
, untagged_variant_decl
);
1770 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1771 "Cannot visit variant field class entry: "
1782 ret
= ctx_decl_scope_register_variant(ctx
->current_scope
, name
, untagged_variant_decl
);
1784 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1785 "Cannot register variant field class in declaration scope: "
1786 "name=\"variant %s\", ret=%d",
1794 * If tagged, create tagged variant and return; otherwise
1795 * return untagged variant.
1798 *variant_decl
= untagged_variant_decl
;
1799 untagged_variant_decl
= NULL
;
1802 * At this point, we have a fresh untagged variant; nobody
1803 * else owns it. Set its tag now.
1805 g_string_assign(untagged_variant_decl
->tag_ref
, tag
);
1806 *variant_decl
= untagged_variant_decl
;
1807 untagged_variant_decl
= NULL
;
1810 BT_ASSERT(!untagged_variant_decl
);
1811 BT_ASSERT(*variant_decl
);
1815 ctf_field_class_destroy(&untagged_variant_decl
->base
);
1816 untagged_variant_decl
= NULL
;
1817 ctf_field_class_destroy(&(*variant_decl
)->base
);
1818 *variant_decl
= NULL
;
1832 static int visit_enum_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*enumerator
,
1833 struct ctf_field_class_enum
*enum_decl
, struct uori
*last
)
1837 struct ctf_node
*iter
;
1838 struct uori start
= {
1852 const char *label
= enumerator
->u
.enumerator
.id
;
1853 struct bt_list_head
*values
= &enumerator
->u
.enumerator
.values
;
1855 bt_list_for_each_entry (iter
, values
, siblings
) {
1856 struct uori
*target
;
1858 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
1859 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1860 "Wrong expression for enumeration field class label: "
1861 "node-type=%d, label=\"%s\"",
1873 switch (iter
->u
.unary_expression
.type
) {
1874 case UNARY_SIGNED_CONSTANT
:
1875 target
->is_signed
= true;
1876 target
->value
.i
= iter
->u
.unary_expression
.u
.signed_constant
;
1878 case UNARY_UNSIGNED_CONSTANT
:
1879 target
->is_signed
= false;
1880 target
->value
.u
= iter
->u
.unary_expression
.u
.unsigned_constant
;
1883 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1884 "Invalid enumeration field class entry: "
1885 "expecting constant signed or unsigned integer: "
1886 "node-type=%d, label=\"%s\"",
1887 iter
->u
.unary_expression
.type
, label
);
1893 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1894 iter
, "Invalid enumeration field class entry: label=\"%s\"", label
);
1910 if (end
.is_signed
) {
1911 last
->value
.i
= end
.value
.i
+ 1;
1913 last
->value
.u
= end
.value
.u
+ 1;
1916 ctf_field_class_enum_map_range(enum_decl
, label
, start
.value
.u
, end
.value
.u
);
1923 static int visit_enum_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1924 struct ctf_node
*container_cls
, struct bt_list_head
*enumerator_list
,
1925 int has_body
, struct ctf_field_class_enum
**enum_decl
)
1929 struct ctf_field_class_int
*integer_decl
= NULL
;
1931 BT_ASSERT(enum_decl
);
1934 /* For named enum (without body), lookup in declaration scope */
1937 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1938 "Bodyless enumeration field class: missing name.");
1943 *enum_decl
= ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, -1, true);
1945 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: "
1952 struct ctf_node
*iter
;
1953 struct uori last_value
= {
1962 if (ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, 1, false)) {
1963 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1964 "Enumeration field class already declared in local scope: "
1972 if (!container_cls
) {
1973 integer_decl
= ctf_field_class_as_int(
1974 ctx_decl_scope_lookup_alias(ctx
->current_scope
, "int", -1, true));
1975 if (!integer_decl
) {
1976 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1977 "Cannot find implicit `int` field class alias for enumeration field class.");
1982 ctf_field_class
*decl
;
1984 ret
= visit_field_class_declarator(ctx
, container_cls
, &qdummy_id
, NULL
, &decl
, NULL
);
1991 integer_decl
= ctf_field_class_as_int(decl
);
1994 BT_ASSERT(integer_decl
);
1996 if (integer_decl
->base
.base
.type
!= CTF_FIELD_CLASS_TYPE_INT
) {
1997 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1998 "Container field class for enumeration field class is not an integer field class: "
2000 integer_decl
->base
.base
.type
);
2005 *enum_decl
= ctf_field_class_enum_create();
2006 BT_ASSERT(*enum_decl
);
2007 (*enum_decl
)->base
.base
.base
.alignment
= integer_decl
->base
.base
.alignment
;
2008 ctf_field_class_int_copy_content(&(*enum_decl
)->base
, integer_decl
);
2009 last_value
.is_signed
= (*enum_decl
)->base
.is_signed
;
2011 bt_list_for_each_entry (iter
, enumerator_list
, siblings
) {
2012 ret
= visit_enum_decl_entry(ctx
, iter
, *enum_decl
, &last_value
);
2014 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
2015 "Cannot visit enumeration field class entry: "
2023 ret
= ctx_decl_scope_register_enum(ctx
->current_scope
, name
, *enum_decl
);
2025 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2026 "Cannot register enumeration field class in declaration scope: "
2037 ctf_field_class_destroy(&(*enum_decl
)->base
.base
.base
);
2041 ctf_field_class_destroy(&integer_decl
->base
.base
);
2042 integer_decl
= NULL
;
2046 static int visit_field_class_specifier(struct ctf_visitor_generate_ir
*ctx
,
2047 struct ctf_node
*cls_specifier_list
,
2048 struct ctf_field_class
**decl
)
2051 GString
*str
= NULL
;
2054 str
= g_string_new("");
2055 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
2057 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2058 cls_specifier_list
, "Cannot get field class specifier list's name: ret=%d", ret
);
2062 *decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, str
->str
, -1, true);
2064 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2065 "Cannot find field class alias: name=\"%s\"", str
->str
);
2073 ctf_field_class_destroy(*decl
);
2078 g_string_free(str
, TRUE
);
2084 static int visit_integer_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2085 struct ctf_field_class_int
**integer_decl
)
2090 struct ctf_node
*expression
;
2091 uint64_t alignment
= 0, size
= 0;
2092 struct ctf_clock_class
*mapped_clock_class
= NULL
;
2093 enum ctf_encoding encoding
= CTF_ENCODING_NONE
;
2094 bt_field_class_integer_preferred_display_base base
=
2095 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2096 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2098 *integer_decl
= NULL
;
2100 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2101 struct ctf_node
*left
, *right
;
2103 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2105 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2107 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2108 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2109 left
->u
.unary_expression
.type
);
2114 if (strcmp(left
->u
.unary_expression
.u
.string
, "signed") == 0) {
2115 if (_IS_SET(&set
, _INTEGER_SIGNED_SET
)) {
2116 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "signed", "integer field class");
2121 signedness
= get_boolean(ctx
, right
);
2122 if (signedness
< 0) {
2123 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2125 "Invalid boolean value for integer field class's `signed` attribute: "
2132 _SET(&set
, _INTEGER_SIGNED_SET
);
2133 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2134 if (_IS_SET(&set
, _INTEGER_BYTE_ORDER_SET
)) {
2135 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order", "integer field class");
2140 byte_order
= get_real_byte_order(ctx
, right
);
2141 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2142 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2144 "Invalid `byte_order` attribute in integer field class: "
2151 _SET(&set
, _INTEGER_BYTE_ORDER_SET
);
2152 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "size") == 0) {
2153 if (_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2154 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "size", "integer field class");
2159 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2160 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2161 "Invalid `size` attribute in integer field class: "
2162 "expecting unsigned constant integer: "
2164 right
->u
.unary_expression
.type
);
2169 size
= right
->u
.unary_expression
.u
.unsigned_constant
;
2171 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2172 "Invalid `size` attribute in integer field class: "
2173 "expecting positive constant integer: "
2178 } else if (size
> 64) {
2179 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2181 "Invalid `size` attribute in integer field class: "
2182 "integer fields over 64 bits are not supported as of this version: "
2189 _SET(&set
, _INTEGER_SIZE_SET
);
2190 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2191 if (_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2192 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align", "integer field class");
2197 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2198 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2199 "Invalid `align` attribute in integer field class: "
2200 "expecting unsigned constant integer: "
2202 right
->u
.unary_expression
.type
);
2207 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2208 if (!is_align_valid(alignment
)) {
2209 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2210 "Invalid `align` attribute in integer field class: "
2211 "expecting power of two: "
2218 _SET(&set
, _INTEGER_ALIGN_SET
);
2219 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "base") == 0) {
2220 if (_IS_SET(&set
, _INTEGER_BASE_SET
)) {
2221 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "base", "integer field class");
2226 switch (right
->u
.unary_expression
.type
) {
2227 case UNARY_UNSIGNED_CONSTANT
:
2229 uint64_t constant
= right
->u
.unary_expression
.u
.unsigned_constant
;
2233 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2236 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2239 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2242 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2245 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2247 "Invalid `base` attribute in integer field class: "
2249 right
->u
.unary_expression
.u
.unsigned_constant
);
2258 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2260 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2262 "Unexpected unary expression for integer field class's `base` attribute.");
2267 if (strcmp(s_right
, "decimal") == 0 || strcmp(s_right
, "dec") == 0 ||
2268 strcmp(s_right
, "d") == 0 || strcmp(s_right
, "i") == 0 ||
2269 strcmp(s_right
, "u") == 0) {
2270 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2271 } else if (strcmp(s_right
, "hexadecimal") == 0 || strcmp(s_right
, "hex") == 0 ||
2272 strcmp(s_right
, "x") == 0 || strcmp(s_right
, "X") == 0 ||
2273 strcmp(s_right
, "p") == 0) {
2274 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2275 } else if (strcmp(s_right
, "octal") == 0 || strcmp(s_right
, "oct") == 0 ||
2276 strcmp(s_right
, "o") == 0) {
2277 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2278 } else if (strcmp(s_right
, "binary") == 0 || strcmp(s_right
, "b") == 0) {
2279 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2281 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2283 "Unexpected unary expression for integer field class's `base` attribute: "
2295 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2296 right
, "Invalid `base` attribute in integer field class: "
2297 "expecting unsigned constant integer or unary string.");
2302 _SET(&set
, _INTEGER_BASE_SET
);
2303 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2306 if (_IS_SET(&set
, _INTEGER_ENCODING_SET
)) {
2307 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "integer field class");
2312 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2313 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2314 right
, "Invalid `encoding` attribute in integer field class: "
2315 "expecting unary string.");
2320 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2322 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2324 "Unexpected unary expression for integer field class's `encoding` attribute.");
2329 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2330 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2331 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2332 encoding
= CTF_ENCODING_UTF8
;
2333 } else if (strcmp(s_right
, "none") == 0) {
2334 encoding
= CTF_ENCODING_NONE
;
2336 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2338 "Invalid `encoding` attribute in integer field class: "
2339 "unknown encoding: encoding=\"%s\"",
2347 _SET(&set
, _INTEGER_ENCODING_SET
);
2348 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "map") == 0) {
2349 const char *clock_name
;
2351 if (_IS_SET(&set
, _INTEGER_MAP_SET
)) {
2352 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "map", "integer field class");
2357 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2358 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2359 "Invalid `map` attribute in integer field class: "
2360 "expecting unary string.");
2365 clock_name
= get_map_clock_name_value(&expression
->u
.ctf_expression
.right
);
2368 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2371 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2373 "Unexpected unary expression for integer field class's `map` attribute.");
2378 _BT_COMP_LOGE_NODE(right
,
2379 "Invalid `map` attribute in integer field class: "
2380 "cannot find clock class at this point: name=\"%s\"",
2382 _SET(&set
, _INTEGER_MAP_SET
);
2387 mapped_clock_class
=
2388 ctf_trace_class_borrow_clock_class_by_name(ctx
->ctf_tc
, clock_name
);
2389 if (!mapped_clock_class
) {
2390 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2392 "Invalid `map` attribute in integer field class: "
2393 "cannot find clock class at this point: name=\"%s\"",
2399 _SET(&set
, _INTEGER_MAP_SET
);
2401 _BT_COMP_LOGW_NODE(left
,
2402 "Unknown attribute in integer field class: "
2404 left
->u
.unary_expression
.u
.string
);
2408 if (!_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2409 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2410 "Missing `size` attribute in integer field class.");
2415 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2416 if (size
% CHAR_BIT
) {
2417 /* Bit-packed alignment */
2420 /* Byte-packed alignment */
2421 alignment
= CHAR_BIT
;
2425 *integer_decl
= ctf_field_class_int_create();
2426 BT_ASSERT(*integer_decl
);
2427 (*integer_decl
)->base
.base
.alignment
= alignment
;
2428 (*integer_decl
)->base
.byte_order
= byte_order
;
2429 (*integer_decl
)->base
.size
= size
;
2430 (*integer_decl
)->is_signed
= (signedness
> 0);
2431 (*integer_decl
)->disp_base
= base
;
2432 (*integer_decl
)->encoding
= encoding
;
2433 (*integer_decl
)->mapped_clock_class
= mapped_clock_class
;
2437 ctf_field_class_destroy(&(*integer_decl
)->base
.base
);
2438 *integer_decl
= NULL
;
2442 static int visit_floating_point_number_decl(struct ctf_visitor_generate_ir
*ctx
,
2443 struct bt_list_head
*expressions
,
2444 struct ctf_field_class_float
**float_decl
)
2448 struct ctf_node
*expression
;
2449 uint64_t alignment
= 1, exp_dig
= 0, mant_dig
= 0;
2450 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2454 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2455 struct ctf_node
*left
, *right
;
2457 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2459 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2461 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2462 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2463 left
->u
.unary_expression
.type
);
2468 if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2469 if (_IS_SET(&set
, _FLOAT_BYTE_ORDER_SET
)) {
2470 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order",
2471 "floating point number field class");
2476 byte_order
= get_real_byte_order(ctx
, right
);
2477 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2478 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2480 "Invalid `byte_order` attribute in floating point number field class: "
2487 _SET(&set
, _FLOAT_BYTE_ORDER_SET
);
2488 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "exp_dig") == 0) {
2489 if (_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2490 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "exp_dig",
2491 "floating point number field class");
2496 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2497 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2499 "Invalid `exp_dig` attribute in floating point number field class: "
2500 "expecting unsigned constant integer: "
2502 right
->u
.unary_expression
.type
);
2507 exp_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2508 _SET(&set
, _FLOAT_EXP_DIG_SET
);
2509 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "mant_dig") == 0) {
2510 if (_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2511 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "mant_dig",
2512 "floating point number field class");
2517 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2518 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2520 "Invalid `mant_dig` attribute in floating point number field class: "
2521 "expecting unsigned constant integer: "
2523 right
->u
.unary_expression
.type
);
2528 mant_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2529 _SET(&set
, _FLOAT_MANT_DIG_SET
);
2530 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2531 if (_IS_SET(&set
, _FLOAT_ALIGN_SET
)) {
2532 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align",
2533 "floating point number field class");
2538 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2539 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2541 "Invalid `align` attribute in floating point number field class: "
2542 "expecting unsigned constant integer: "
2544 right
->u
.unary_expression
.type
);
2549 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2551 if (!is_align_valid(alignment
)) {
2552 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2554 "Invalid `align` attribute in floating point number field class: "
2555 "expecting power of two: "
2562 _SET(&set
, _FLOAT_ALIGN_SET
);
2564 _BT_COMP_LOGW_NODE(left
,
2565 "Unknown attribute in floating point number field class: "
2567 left
->u
.unary_expression
.u
.string
);
2571 if (!_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2572 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2573 "Missing `mant_dig` attribute in floating point number field class.");
2578 if (!_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2579 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2580 "Missing `exp_dig` attribute in floating point number field class.");
2585 if (mant_dig
!= 24 && mant_dig
!= 53) {
2586 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53.");
2591 if (mant_dig
== 24 && exp_dig
!= 8) {
2592 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2593 "`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2598 if (mant_dig
== 53 && exp_dig
!= 11) {
2599 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2600 "`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2605 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2606 if ((mant_dig
+ exp_dig
) % CHAR_BIT
) {
2607 /* Bit-packed alignment */
2610 /* Byte-packed alignment */
2611 alignment
= CHAR_BIT
;
2615 *float_decl
= ctf_field_class_float_create();
2616 BT_ASSERT(*float_decl
);
2617 (*float_decl
)->base
.base
.alignment
= alignment
;
2618 (*float_decl
)->base
.byte_order
= byte_order
;
2619 (*float_decl
)->base
.size
= mant_dig
+ exp_dig
;
2623 ctf_field_class_destroy(&(*float_decl
)->base
.base
);
2628 static int visit_string_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2629 struct ctf_field_class_string
**string_decl
)
2633 struct ctf_node
*expression
;
2634 enum ctf_encoding encoding
= CTF_ENCODING_UTF8
;
2636 *string_decl
= NULL
;
2638 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2639 struct ctf_node
*left
, *right
;
2641 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2643 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2645 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2646 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2647 left
->u
.unary_expression
.type
);
2652 if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2655 if (_IS_SET(&set
, _STRING_ENCODING_SET
)) {
2656 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "string field class");
2661 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2662 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2663 right
, "Invalid `encoding` attribute in string field class: "
2664 "expecting unary string.");
2669 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2671 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2673 "Unexpected unary expression for string field class's `encoding` attribute.");
2678 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2679 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2680 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2681 encoding
= CTF_ENCODING_UTF8
;
2682 } else if (strcmp(s_right
, "none") == 0) {
2683 encoding
= CTF_ENCODING_NONE
;
2685 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2687 "Invalid `encoding` attribute in string field class: "
2688 "unknown encoding: encoding=\"%s\"",
2696 _SET(&set
, _STRING_ENCODING_SET
);
2698 _BT_COMP_LOGW_NODE(left
,
2699 "Unknown attribute in string field class: "
2701 left
->u
.unary_expression
.u
.string
);
2705 *string_decl
= ctf_field_class_string_create();
2706 BT_ASSERT(*string_decl
);
2707 (*string_decl
)->encoding
= encoding
;
2711 ctf_field_class_destroy(&(*string_decl
)->base
);
2712 *string_decl
= NULL
;
2716 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
2717 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
)
2720 struct ctf_node
*first
, *node
;
2724 if (ts_list
->type
!= NODE_TYPE_SPECIFIER_LIST
) {
2725 _BT_COMP_LOGE_APPEND_CAUSE_NODE(ts_list
, "Unexpected node type: node-type=%d",
2731 first
= _BT_LIST_FIRST_ENTRY(&ts_list
->u
.field_class_specifier_list
.head
, struct ctf_node
,
2733 if (first
->type
!= NODE_TYPE_SPECIFIER
) {
2734 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type=%d", first
->type
);
2739 node
= first
->u
.field_class_specifier
.node
;
2741 switch (first
->u
.field_class_specifier
.type
) {
2742 case TYPESPEC_INTEGER
:
2744 ctf_field_class_int
*int_decl
;
2746 ret
= visit_integer_decl(ctx
, &node
->u
.integer
.expressions
, &int_decl
);
2748 BT_ASSERT(!int_decl
);
2752 *decl
= &int_decl
->base
.base
;
2755 case TYPESPEC_FLOATING_POINT
:
2757 ctf_field_class_float
*float_decl
;
2760 visit_floating_point_number_decl(ctx
, &node
->u
.floating_point
.expressions
, &float_decl
);
2762 BT_ASSERT(!float_decl
);
2766 *decl
= &float_decl
->base
.base
;
2769 case TYPESPEC_STRING
:
2771 ctf_field_class_string
*string_decl
;
2773 ret
= visit_string_decl(ctx
, &node
->u
.string
.expressions
, &string_decl
);
2775 BT_ASSERT(!string_decl
);
2779 *decl
= &string_decl
->base
;
2782 case TYPESPEC_STRUCT
:
2784 ctf_field_class_struct
*struct_decl
;
2786 ret
= visit_struct_decl(ctx
, node
->u
._struct
.name
, &node
->u
._struct
.declaration_list
,
2787 node
->u
._struct
.has_body
, &node
->u
._struct
.min_align
, &struct_decl
);
2789 BT_ASSERT(!struct_decl
);
2793 *decl
= &struct_decl
->base
;
2796 case TYPESPEC_VARIANT
:
2798 ctf_field_class_variant
*variant_decl
;
2800 ret
= visit_variant_decl(ctx
, node
->u
.variant
.name
, node
->u
.variant
.choice
,
2801 &node
->u
.variant
.declaration_list
, node
->u
.variant
.has_body
,
2804 BT_ASSERT(!variant_decl
);
2808 *decl
= &variant_decl
->base
;
2813 ctf_field_class_enum
*enum_decl
;
2815 ret
= visit_enum_decl(ctx
, node
->u
._enum
.enum_id
, node
->u
._enum
.container_field_class
,
2816 &node
->u
._enum
.enumerator_list
, node
->u
._enum
.has_body
, &enum_decl
);
2818 BT_ASSERT(!enum_decl
);
2822 *decl
= &enum_decl
->base
.base
.base
;
2827 case TYPESPEC_SHORT
:
2830 case TYPESPEC_FLOAT
:
2831 case TYPESPEC_DOUBLE
:
2832 case TYPESPEC_SIGNED
:
2833 case TYPESPEC_UNSIGNED
:
2835 case TYPESPEC_COMPLEX
:
2836 case TYPESPEC_IMAGINARY
:
2837 case TYPESPEC_CONST
:
2838 case TYPESPEC_ID_TYPE
:
2839 ret
= visit_field_class_specifier(ctx
, ts_list
, decl
);
2841 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Cannot visit field class specifier: ret=%d",
2848 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
,
2849 "Unexpected field class specifier type: node-type=%d",
2850 first
->u
.field_class_specifier
.type
);
2859 ctf_field_class_destroy(*decl
);
2864 static int visit_event_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
2865 struct ctf_event_class
*event_class
, uint64_t *stream_id
,
2871 switch (node
->type
) {
2873 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
2874 &node
->u
.field_class_def
.field_class_declarators
);
2876 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in event class.");
2880 case NODE_TYPEALIAS
:
2881 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
2882 node
->u
.field_class_alias
.alias
);
2884 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2885 "Cannot add field class alias found in event class.");
2889 case NODE_CTF_EXPRESSION
:
2891 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
2893 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
2898 if (strcmp(left
, "name") == 0) {
2899 /* This is already known at this stage */
2900 if (_IS_SET(set
, _EVENT_NAME_SET
)) {
2901 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "name", "event class");
2906 _SET(set
, _EVENT_NAME_SET
);
2907 } else if (strcmp(left
, "id") == 0) {
2910 if (_IS_SET(set
, _EVENT_ID_SET
)) {
2911 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "event class");
2916 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
2917 /* Only read "id" if get_unary_unsigned() succeeded. */
2918 if (ret
|| (!ret
&& id
< 0)) {
2919 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2920 node
, "Unexpected unary expression for event class's `id` attribute.");
2925 event_class
->id
= id
;
2926 _SET(set
, _EVENT_ID_SET
);
2927 } else if (strcmp(left
, "stream_id") == 0) {
2928 if (_IS_SET(set
, _EVENT_STREAM_ID_SET
)) {
2929 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "stream_id", "event class");
2934 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, stream_id
);
2937 * Only read "stream_id" if get_unary_unsigned()
2941 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2942 node
, "Unexpected unary expression for event class's `stream_id` attribute.");
2947 _SET(set
, _EVENT_STREAM_ID_SET
);
2948 } else if (strcmp(left
, "context") == 0) {
2949 if (_IS_SET(set
, _EVENT_CONTEXT_SET
)) {
2950 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `context` entry in event class.");
2955 ret
= visit_field_class_specifier_list(
2956 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2957 &event_class
->spec_context_fc
);
2959 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2960 "Cannot create event class's context field class.");
2964 BT_ASSERT(event_class
->spec_context_fc
);
2965 _SET(set
, _EVENT_CONTEXT_SET
);
2966 } else if (strcmp(left
, "fields") == 0) {
2967 if (_IS_SET(set
, _EVENT_FIELDS_SET
)) {
2968 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `fields` entry in event class.");
2973 ret
= visit_field_class_specifier_list(
2974 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2975 &event_class
->payload_fc
);
2977 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2978 "Cannot create event class's payload field class.");
2982 BT_ASSERT(event_class
->payload_fc
);
2983 _SET(set
, _EVENT_FIELDS_SET
);
2984 } else if (strcmp(left
, "loglevel") == 0) {
2985 uint64_t loglevel_value
;
2986 bool is_log_level_known
= true;
2987 bt_event_class_log_level log_level
;
2989 if (_IS_SET(set
, _EVENT_LOG_LEVEL_SET
)) {
2990 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "loglevel", "event class");
2995 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &loglevel_value
);
2997 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2998 node
, "Unexpected unary expression for event class's `loglevel` attribute.");
3003 switch (loglevel_value
) {
3005 log_level
= BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
;
3008 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ALERT
;
3011 log_level
= BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
;
3014 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ERROR
;
3017 log_level
= BT_EVENT_CLASS_LOG_LEVEL_WARNING
;
3020 log_level
= BT_EVENT_CLASS_LOG_LEVEL_NOTICE
;
3023 log_level
= BT_EVENT_CLASS_LOG_LEVEL_INFO
;
3026 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
;
3029 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
;
3032 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
;
3035 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
;
3038 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
;
3041 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
;
3044 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
;
3047 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG
;
3050 is_log_level_known
= false;
3053 "Not setting event class's log level because its value is unknown: "
3054 "log-level=%" PRIu64
,
3058 if (is_log_level_known
) {
3059 ctf_event_class_set_log_level(event_class
, log_level
);
3062 _SET(set
, _EVENT_LOG_LEVEL_SET
);
3063 } else if (strcmp(left
, "model.emf.uri") == 0) {
3066 if (_IS_SET(set
, _EVENT_MODEL_EMF_URI_SET
)) {
3067 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "model.emf.uri", "event class");
3072 right
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.right
);
3074 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3076 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3081 if (strlen(right
) == 0) {
3082 _BT_COMP_LOGW_NODE(node
, "Not setting event class's EMF URI because it's empty.");
3084 g_string_assign(event_class
->emf_uri
, right
);
3088 _SET(set
, _EVENT_MODEL_EMF_URI_SET
);
3090 _BT_COMP_LOGW_NODE(node
,
3091 "Unknown attribute in event class: "
3114 static char *get_event_decl_name(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3118 struct ctf_node
*iter
;
3119 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3121 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3122 if (iter
->type
!= NODE_CTF_EXPRESSION
) {
3126 left
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.left
);
3128 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot concatenate unary strings.");
3132 if (strcmp(left
, "name") == 0) {
3133 name
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.right
);
3135 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3136 iter
, "Unexpected unary expression for event class's `name` attribute.");
3156 static int visit_event_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3160 struct ctf_node
*iter
;
3161 uint64_t stream_id
= 0;
3162 char *event_name
= NULL
;
3163 struct ctf_event_class
*event_class
= NULL
;
3164 struct ctf_stream_class
*stream_class
= NULL
;
3165 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3166 bool pop_scope
= false;
3168 if (node
->visited
) {
3172 node
->visited
= TRUE
;
3173 event_name
= get_event_decl_name(ctx
, node
);
3175 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `name` attribute in event class.");
3180 event_class
= ctf_event_class_create();
3181 BT_ASSERT(event_class
);
3182 g_string_assign(event_class
->name
, event_name
);
3183 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3186 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3187 ret
= visit_event_decl_entry(ctx
, iter
, event_class
, &stream_id
, &set
);
3189 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3190 "Cannot visit event class's entry: "
3197 if (!_IS_SET(&set
, _EVENT_STREAM_ID_SET
)) {
3199 * Allow missing stream_id if there is only a single
3202 switch (ctx
->ctf_tc
->stream_classes
->len
) {
3204 /* Create implicit stream class if there's none */
3206 stream_class
= ctf_stream_class_create();
3207 BT_ASSERT(stream_class
);
3208 stream_class
->id
= stream_id
;
3209 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3212 /* Single stream class: get its ID */
3213 stream_class
= (ctf_stream_class
*) ctx
->ctf_tc
->stream_classes
->pdata
[0];
3214 stream_id
= stream_class
->id
;
3217 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `stream_id` attribute in event class.");
3223 /* We have the stream ID now; get the stream class if found */
3224 if (!stream_class
) {
3225 stream_class
= ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_id
);
3226 if (!stream_class
) {
3227 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3228 "Cannot find stream class at this point: "
3236 BT_ASSERT(stream_class
);
3238 if (!_IS_SET(&set
, _EVENT_ID_SET
)) {
3239 /* Allow only one event without ID per stream */
3240 if (stream_class
->event_classes
->len
!= 0) {
3241 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `id` attribute in event class.");
3247 event_class
->id
= 0;
3250 if (ctf_stream_class_borrow_event_class_by_id(stream_class
, event_class
->id
)) {
3251 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3252 "Duplicate event class (same ID) in the same stream class: "
3259 ctf_stream_class_append_event_class(stream_class
, event_class
);
3264 ctf_event_class_destroy(event_class
);
3281 static int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3282 struct ctf_field_class
*fc
)
3284 struct ctf_clock_class
*clock_class_to_map_to
= NULL
;
3285 uint64_t clock_class_count
;
3291 if (fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&& fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3295 ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
3297 if (int_fc
->mapped_clock_class
) {
3298 /* Already mapped */
3302 clock_class_count
= ctx
->ctf_tc
->clock_classes
->len
;
3304 switch (clock_class_count
) {
3307 * No clock class exists in the trace at this point. Create an
3308 * implicit one at 1 GHz, named `default`, and use this clock
3311 clock_class_to_map_to
= ctf_clock_class_create();
3312 BT_ASSERT(clock_class_to_map_to
);
3313 clock_class_to_map_to
->frequency
= UINT64_C(1000000000);
3314 g_string_assign(clock_class_to_map_to
->name
, "default");
3315 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock_class_to_map_to
);
3319 * Only one clock class exists in the trace at this point: use
3322 clock_class_to_map_to
= (ctf_clock_class
*) ctx
->ctf_tc
->clock_classes
->pdata
[0];
3326 * Timestamp field not mapped to a clock class and there's more
3327 * than one clock class in the trace: this is an error.
3329 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3330 "Timestamp field found with no mapped clock class, "
3331 "but there's more than one clock class in the trace at this point.");
3335 BT_ASSERT(clock_class_to_map_to
);
3336 int_fc
->mapped_clock_class
= clock_class_to_map_to
;
3341 static int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3342 struct ctf_field_class
*root_fc
,
3343 const char *field_name
)
3347 struct ctf_field_class_struct
*struct_fc
= (ctf_field_class_struct
*) root_fc
;
3348 struct ctf_field_class_variant
*var_fc
= (ctf_field_class_variant
*) root_fc
;
3354 if (root_fc
->type
!= CTF_FIELD_CLASS_TYPE_STRUCT
&&
3355 root_fc
->type
!= CTF_FIELD_CLASS_TYPE_VARIANT
) {
3359 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3360 count
= struct_fc
->members
->len
;
3362 count
= var_fc
->options
->len
;
3365 for (i
= 0; i
< count
; i
++) {
3366 struct ctf_named_field_class
*named_fc
= NULL
;
3368 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3369 named_fc
= ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
3370 } else if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
3371 named_fc
= ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
3376 if (strcmp(named_fc
->name
->str
, field_name
) == 0) {
3377 ret
= auto_map_field_to_trace_clock_class(ctx
, named_fc
->fc
);
3379 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3380 "Cannot automatically map field to trace's clock class: "
3381 "field-name=\"%s\"",
3387 ret
= auto_map_fields_to_trace_clock_class(ctx
, named_fc
->fc
, field_name
);
3389 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3390 "Cannot automatically map structure or variant field class's fields to trace's clock class: "
3391 "field-name=\"%s\", root-field-name=\"%s\"",
3392 field_name
, named_fc
->name
->str
);
3401 static int visit_stream_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3402 struct ctf_stream_class
*stream_class
, int *set
)
3407 switch (node
->type
) {
3409 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3410 &node
->u
.field_class_def
.field_class_declarators
);
3412 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in stream class.");
3416 case NODE_TYPEALIAS
:
3417 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3418 node
->u
.field_class_alias
.alias
);
3420 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3421 "Cannot add field class alias found in stream class.");
3425 case NODE_CTF_EXPRESSION
:
3427 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3429 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3434 if (strcmp(left
, "id") == 0) {
3437 if (_IS_SET(set
, _STREAM_ID_SET
)) {
3438 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "stream declaration");
3443 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
3445 /* Only read "id" if get_unary_unsigned() succeeded. */
3446 if (ret
|| (!ret
&& id
< 0)) {
3447 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3448 node
, "Unexpected unary expression for stream class's `id` attribute.");
3453 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, id
)) {
3454 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3455 node
, "Duplicate stream class (same ID): id=%" PRId64
, id
);
3460 stream_class
->id
= id
;
3461 _SET(set
, _STREAM_ID_SET
);
3462 } else if (strcmp(left
, "event.header") == 0) {
3463 if (_IS_SET(set
, _STREAM_EVENT_HEADER_SET
)) {
3464 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3465 "Duplicate `event.header` entry in stream class.");
3470 ret
= visit_field_class_specifier_list(
3471 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3472 &stream_class
->event_header_fc
);
3474 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3475 node
, "Cannot create stream class's event header field class.");
3479 BT_ASSERT(stream_class
->event_header_fc
);
3480 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->event_header_fc
,
3483 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3485 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3489 _SET(set
, _STREAM_EVENT_HEADER_SET
);
3490 } else if (strcmp(left
, "event.context") == 0) {
3491 if (_IS_SET(set
, _STREAM_EVENT_CONTEXT_SET
)) {
3492 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3493 "Duplicate `event.context` entry in stream class.");
3498 ret
= visit_field_class_specifier_list(
3499 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3500 &stream_class
->event_common_context_fc
);
3502 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3503 node
, "Cannot create stream class's event context field class.");
3507 BT_ASSERT(stream_class
->event_common_context_fc
);
3508 _SET(set
, _STREAM_EVENT_CONTEXT_SET
);
3509 } else if (strcmp(left
, "packet.context") == 0) {
3510 if (_IS_SET(set
, _STREAM_PACKET_CONTEXT_SET
)) {
3511 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3512 node
, "Duplicate `packet.context` entry in stream class.");
3517 ret
= visit_field_class_specifier_list(
3518 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3519 &stream_class
->packet_context_fc
);
3521 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3522 node
, "Cannot create stream class's packet context field class.");
3526 BT_ASSERT(stream_class
->packet_context_fc
);
3527 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3530 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3532 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3536 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3539 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3541 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3545 _SET(set
, _STREAM_PACKET_CONTEXT_SET
);
3547 _BT_COMP_LOGW_NODE(node
,
3548 "Unknown attribute in stream class: "
3570 static int visit_stream_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3574 struct ctf_node
*iter
;
3575 struct ctf_stream_class
*stream_class
= NULL
;
3576 struct bt_list_head
*decl_list
= &node
->u
.stream
.declaration_list
;
3578 if (node
->visited
) {
3582 node
->visited
= TRUE
;
3583 stream_class
= ctf_stream_class_create();
3584 BT_ASSERT(stream_class
);
3585 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3587 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3588 ret
= visit_stream_decl_entry(ctx
, iter
, stream_class
, &set
);
3590 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3591 "Cannot visit stream class's entry: "
3601 if (_IS_SET(&set
, _STREAM_ID_SET
)) {
3602 /* Check that packet header has `stream_id` field */
3603 struct ctf_named_field_class
*named_fc
= NULL
;
3605 if (!ctx
->ctf_tc
->packet_header_fc
) {
3606 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Stream class has a `id` attribute, "
3607 "but trace has no packet header field class.");
3612 named_fc
= ctf_field_class_struct_borrow_member_by_name(
3613 ctf_field_class_as_struct(ctx
->ctf_tc
->packet_header_fc
), "stream_id");
3615 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3616 node
, "Stream class has a `id` attribute, "
3617 "but trace's packet header field class has no `stream_id` field.");
3622 if (named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3623 named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3624 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3626 "Stream class has a `id` attribute, "
3627 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3632 /* Allow only _one_ ID-less stream */
3633 if (ctx
->ctf_tc
->stream_classes
->len
!= 0) {
3634 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3636 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3641 /* Automatic ID: 0 */
3642 stream_class
->id
= 0;
3646 * Make sure that this stream class's ID is currently unique in
3649 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_class
->id
)) {
3650 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate stream class (same ID): id=%" PRId64
,
3656 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3657 stream_class
= NULL
;
3661 ctf_stream_class_destroy(stream_class
);
3662 stream_class
= NULL
;
3668 static int visit_trace_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3675 switch (node
->type
) {
3677 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3678 &node
->u
.field_class_def
.field_class_declarators
);
3680 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3681 node
, "Cannot add field class found in trace (`trace` block).");
3685 case NODE_TYPEALIAS
:
3686 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3687 node
->u
.field_class_alias
.alias
);
3689 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3690 node
, "Cannot add field class alias found in trace (`trace` block).");
3694 case NODE_CTF_EXPRESSION
:
3696 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3698 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3703 if (strcmp(left
, "major") == 0) {
3704 if (_IS_SET(set
, _TRACE_MAJOR_SET
)) {
3705 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "major", "trace");
3710 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3712 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3713 node
, "Unexpected unary expression for trace's `major` attribute.");
3719 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3720 "Invalid trace's `minor` attribute: expecting 1.");
3725 ctx
->ctf_tc
->major
= val
;
3726 _SET(set
, _TRACE_MAJOR_SET
);
3727 } else if (strcmp(left
, "minor") == 0) {
3728 if (_IS_SET(set
, _TRACE_MINOR_SET
)) {
3729 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "minor", "trace");
3734 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3736 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3737 node
, "Unexpected unary expression for trace's `minor` attribute.");
3743 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3744 "Invalid trace's `minor` attribute: expecting 8.");
3749 ctx
->ctf_tc
->minor
= val
;
3750 _SET(set
, _TRACE_MINOR_SET
);
3751 } else if (strcmp(left
, "uuid") == 0) {
3752 if (_IS_SET(set
, _TRACE_UUID_SET
)) {
3753 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "uuid", "trace");
3758 ret
= get_unary_uuid(ctx
, &node
->u
.ctf_expression
.right
, ctx
->ctf_tc
->uuid
);
3760 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid trace's `uuid` attribute.");
3764 ctx
->ctf_tc
->is_uuid_set
= true;
3765 _SET(set
, _TRACE_UUID_SET
);
3766 } else if (strcmp(left
, "byte_order") == 0) {
3767 /* Default byte order is already known at this stage */
3768 if (_IS_SET(set
, _TRACE_BYTE_ORDER_SET
)) {
3769 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
3774 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
!= CTF_BYTE_ORDER_UNKNOWN
);
3775 _SET(set
, _TRACE_BYTE_ORDER_SET
);
3776 } else if (strcmp(left
, "packet.header") == 0) {
3777 if (_IS_SET(set
, _TRACE_PACKET_HEADER_SET
)) {
3778 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `packet.header` entry in trace.");
3783 ret
= visit_field_class_specifier_list(
3784 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3785 &ctx
->ctf_tc
->packet_header_fc
);
3787 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3788 "Cannot create trace's packet header field class.");
3792 BT_ASSERT(ctx
->ctf_tc
->packet_header_fc
);
3793 _SET(set
, _TRACE_PACKET_HEADER_SET
);
3795 _BT_COMP_LOGW_NODE(node
,
3796 "Unknown attribute in stream class: "
3806 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unknown expression in trace.");
3818 static int visit_trace_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3822 struct ctf_node
*iter
;
3823 struct bt_list_head
*decl_list
= &node
->u
.trace
.declaration_list
;
3825 if (node
->visited
) {
3829 node
->visited
= TRUE
;
3831 if (ctx
->is_trace_visited
) {
3832 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
3837 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3839 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3840 ret
= visit_trace_decl_entry(ctx
, iter
, &set
);
3842 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3843 "Cannot visit trace's entry (`trace` block): "
3853 if (!_IS_SET(&set
, _TRACE_MAJOR_SET
)) {
3854 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3855 "Missing `major` attribute in trace (`trace` block).");
3860 if (!_IS_SET(&set
, _TRACE_MINOR_SET
)) {
3861 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3862 "Missing `minor` attribute in trace (`trace` block).");
3867 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3868 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3869 "Missing `byte_order` attribute in trace (`trace` block).");
3874 ctx
->is_trace_visited
= true;
3883 static int visit_env(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3887 struct ctf_node
*entry_node
;
3888 struct bt_list_head
*decl_list
= &node
->u
.env
.declaration_list
;
3890 if (node
->visited
) {
3894 node
->visited
= TRUE
;
3896 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
3897 struct bt_list_head
*right_head
= &entry_node
->u
.ctf_expression
.right
;
3899 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
3900 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
3901 "Wrong expression in environment entry: "
3908 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
3910 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot get environment entry's name.");
3915 if (is_unary_string(right_head
)) {
3916 char *right
= ctf_ast_concatenate_unary_strings(right_head
);
3919 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3921 "Unexpected unary expression for environment entry's value: "
3928 if (strcmp(left
, "tracer_name") == 0) {
3929 if (strncmp(right
, "lttng", 5) == 0) {
3930 BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: "
3931 "tracer-name=\"%s\"",
3933 ctx
->is_lttng
= true;
3937 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
,
3940 } else if (is_unary_unsigned(right_head
) || is_unary_signed(right_head
)) {
3943 if (is_unary_unsigned(right_head
)) {
3944 ret
= get_unary_unsigned(ctx
, right_head
, (uint64_t *) &v
);
3946 ret
= get_unary_signed(right_head
, &v
);
3949 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3951 "Unexpected unary expression for environment entry's value: "
3958 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
,
3961 _BT_COMP_LOGW_NODE(entry_node
,
3962 "Environment entry has unknown type: "
3979 static int set_trace_byte_order(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*trace_node
)
3984 struct ctf_node
*node
;
3985 struct bt_list_head
*decl_list
= &trace_node
->u
.trace
.declaration_list
;
3987 bt_list_for_each_entry (node
, decl_list
, siblings
) {
3988 if (node
->type
== NODE_CTF_EXPRESSION
) {
3989 struct ctf_node
*right_node
;
3991 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3993 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3998 if (strcmp(left
, "byte_order") == 0) {
3999 enum ctf_byte_order bo
;
4001 if (_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4002 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
4007 _SET(&set
, _TRACE_BYTE_ORDER_SET
);
4009 _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4010 bo
= byte_order_from_unary_expr(ctx
, right_node
);
4011 if (bo
== CTF_BYTE_ORDER_UNKNOWN
) {
4012 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4013 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4014 "expecting `le`, `be`, or `network`.");
4017 } else if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
4018 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4019 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4020 "cannot be set to `native` here.");
4025 ctx
->ctf_tc
->default_byte_order
= bo
;
4033 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4034 _BT_COMP_LOGE_APPEND_CAUSE_NODE(trace_node
,
4035 "Missing `byte_order` attribute in trace (`trace` block).");
4047 static int visit_clock_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
4048 struct ctf_clock_class
*clock
, int *set
, int64_t *offset_seconds
,
4049 uint64_t *offset_cycles
)
4054 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4055 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
4061 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
4063 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot concatenate unary strings.");
4068 if (strcmp(left
, "name") == 0) {
4071 if (_IS_SET(set
, _CLOCK_NAME_SET
)) {
4072 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "name", "clock class");
4077 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4079 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4080 entry_node
, "Unexpected unary expression for clock class's `name` attribute.");
4085 g_string_assign(clock
->name
, right
);
4087 _SET(set
, _CLOCK_NAME_SET
);
4088 } else if (strcmp(left
, "uuid") == 0) {
4091 if (_IS_SET(set
, _CLOCK_UUID_SET
)) {
4092 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "uuid", "clock class");
4097 ret
= get_unary_uuid(ctx
, &entry_node
->u
.ctf_expression
.right
, uuid
);
4099 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Invalid clock class's `uuid` attribute.");
4103 clock
->has_uuid
= true;
4104 bt_uuid_copy(clock
->uuid
, uuid
);
4105 _SET(set
, _CLOCK_UUID_SET
);
4106 } else if (strcmp(left
, "description") == 0) {
4109 if (_IS_SET(set
, _CLOCK_DESCRIPTION_SET
)) {
4110 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "description", "clock class");
4115 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4117 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4119 "Unexpected unary expression for clock class's `description` attribute.");
4124 g_string_assign(clock
->description
, right
);
4126 _SET(set
, _CLOCK_DESCRIPTION_SET
);
4127 } else if (strcmp(left
, "freq") == 0) {
4128 uint64_t freq
= UINT64_C(-1);
4130 if (_IS_SET(set
, _CLOCK_FREQ_SET
)) {
4131 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "freq", "clock class");
4136 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &freq
);
4138 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4139 entry_node
, "Unexpected unary expression for clock class's `freq` attribute.");
4144 if (freq
== UINT64_C(-1) || freq
== 0) {
4145 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4146 "Invalid clock class frequency: freq=%" PRIu64
, freq
);
4151 clock
->frequency
= freq
;
4152 _SET(set
, _CLOCK_FREQ_SET
);
4153 } else if (strcmp(left
, "precision") == 0) {
4156 if (_IS_SET(set
, _CLOCK_PRECISION_SET
)) {
4157 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "precision", "clock class");
4162 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &precision
);
4164 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4165 entry_node
, "Unexpected unary expression for clock class's `precision` attribute.");
4170 clock
->precision
= precision
;
4171 _SET(set
, _CLOCK_PRECISION_SET
);
4172 } else if (strcmp(left
, "offset_s") == 0) {
4173 if (_IS_SET(set
, _CLOCK_OFFSET_S_SET
)) {
4174 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset_s", "clock class");
4179 ret
= get_unary_signed(&entry_node
->u
.ctf_expression
.right
, offset_seconds
);
4181 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4182 entry_node
, "Unexpected unary expression for clock class's `offset_s` attribute.");
4187 _SET(set
, _CLOCK_OFFSET_S_SET
);
4188 } else if (strcmp(left
, "offset") == 0) {
4189 if (_IS_SET(set
, _CLOCK_OFFSET_SET
)) {
4190 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset", "clock class");
4195 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, offset_cycles
);
4197 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4198 entry_node
, "Unexpected unary expression for clock class's `offset` attribute.");
4203 _SET(set
, _CLOCK_OFFSET_SET
);
4204 } else if (strcmp(left
, "absolute") == 0) {
4205 struct ctf_node
*right
;
4207 if (_IS_SET(set
, _CLOCK_ABSOLUTE_SET
)) {
4208 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "absolute", "clock class");
4214 _BT_LIST_FIRST_ENTRY(&entry_node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4215 ret
= get_boolean(ctx
, right
);
4217 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4218 entry_node
, "Unexpected unary expression for clock class's `absolute` attribute.");
4223 clock
->is_absolute
= ret
;
4224 _SET(set
, _CLOCK_ABSOLUTE_SET
);
4226 _BT_COMP_LOGW_NODE(entry_node
, "Unknown attribute in clock class: attr-name=\"%s\"", left
);
4238 static inline uint64_t cycles_from_ns(uint64_t frequency
, uint64_t ns
)
4243 if (frequency
== UINT64_C(1000000000)) {
4246 cycles
= (uint64_t) (((double) ns
* (double) frequency
) / 1e9
);
4252 static void calibrate_clock_class_offsets(int64_t *offset_seconds
, uint64_t *offset_cycles
,
4255 if (*offset_cycles
>= freq
) {
4256 const uint64_t s_in_offset_cycles
= *offset_cycles
/ freq
;
4258 *offset_seconds
+= (int64_t) s_in_offset_cycles
;
4259 *offset_cycles
-= (s_in_offset_cycles
* freq
);
4263 static void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir
*ctx
,
4264 struct ctf_clock_class
*clock
)
4266 if (ctx
->decoder_config
.force_clock_class_origin_unix_epoch
) {
4267 clock
->is_absolute
= true;
4273 static void apply_clock_class_offset(struct ctf_visitor_generate_ir
*ctx
,
4274 struct ctf_clock_class
*clock
)
4277 int64_t offset_s_to_apply
= ctx
->decoder_config
.clock_class_offset_s
;
4278 uint64_t offset_ns_to_apply
;
4279 int64_t cur_offset_s
;
4280 uint64_t cur_offset_cycles
;
4282 if (ctx
->decoder_config
.clock_class_offset_s
== 0 &&
4283 ctx
->decoder_config
.clock_class_offset_ns
== 0) {
4287 /* Transfer nanoseconds to seconds as much as possible */
4288 if (ctx
->decoder_config
.clock_class_offset_ns
< 0) {
4289 const int64_t abs_ns
= -ctx
->decoder_config
.clock_class_offset_ns
;
4290 const int64_t abs_extra_s
= abs_ns
/ INT64_C(1000000000) + 1;
4291 const int64_t extra_s
= -abs_extra_s
;
4292 const int64_t offset_ns
=
4293 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4295 BT_ASSERT(offset_ns
> 0);
4296 offset_ns_to_apply
= (uint64_t) offset_ns
;
4297 offset_s_to_apply
+= extra_s
;
4299 const int64_t extra_s
= ctx
->decoder_config
.clock_class_offset_ns
/ INT64_C(1000000000);
4300 const int64_t offset_ns
=
4301 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4303 BT_ASSERT(offset_ns
>= 0);
4304 offset_ns_to_apply
= (uint64_t) offset_ns
;
4305 offset_s_to_apply
+= extra_s
;
4308 freq
= clock
->frequency
;
4309 cur_offset_s
= clock
->offset_seconds
;
4310 cur_offset_cycles
= clock
->offset_cycles
;
4313 cur_offset_s
+= offset_s_to_apply
;
4314 cur_offset_cycles
+= cycles_from_ns(freq
, offset_ns_to_apply
);
4317 * Recalibrate offsets because the part in cycles can be greater
4318 * than the frequency at this point.
4320 calibrate_clock_class_offsets(&cur_offset_s
, &cur_offset_cycles
, freq
);
4322 /* Set final offsets */
4323 clock
->offset_seconds
= cur_offset_s
;
4324 clock
->offset_cycles
= cur_offset_cycles
;
4330 static int visit_clock_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*clock_node
)
4334 struct ctf_clock_class
*clock
;
4335 struct ctf_node
*entry_node
;
4336 struct bt_list_head
*decl_list
= &clock_node
->u
.clock
.declaration_list
;
4337 const char *clock_class_name
;
4338 int64_t offset_seconds
= 0;
4339 uint64_t offset_cycles
= 0;
4342 if (clock_node
->visited
) {
4346 clock_node
->visited
= TRUE
;
4348 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4349 clock
= ctf_clock_class_create();
4351 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
, "Cannot create default clock class.");
4356 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
4357 ret
= visit_clock_decl_entry(ctx
, entry_node
, clock
, &set
, &offset_seconds
, &offset_cycles
);
4359 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot visit clock class's entry: ret=%d",
4365 if (!_IS_SET(&set
, _CLOCK_NAME_SET
)) {
4366 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
, "Missing `name` attribute in clock class.");
4371 clock_class_name
= clock
->name
->str
;
4372 BT_ASSERT(clock_class_name
);
4373 if (ctx
->is_lttng
&& strcmp(clock_class_name
, "monotonic") == 0) {
4375 * Old versions of LTTng forgot to set its clock class
4376 * as absolute, even if it is. This is important because
4377 * it's a condition to be able to sort messages
4378 * from different sources.
4380 clock
->is_absolute
= true;
4384 * Adjust offsets so that the part in cycles is less than the
4385 * frequency (move to the part in seconds).
4387 freq
= clock
->frequency
;
4388 calibrate_clock_class_offsets(&offset_seconds
, &offset_cycles
, freq
);
4389 BT_ASSERT(offset_cycles
< clock
->frequency
);
4390 clock
->offset_seconds
= offset_seconds
;
4391 clock
->offset_cycles
= offset_cycles
;
4392 apply_clock_class_offset(ctx
, clock
);
4393 apply_clock_class_is_absolute(ctx
, clock
);
4394 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock
);
4399 ctf_clock_class_destroy(clock
);
4405 static int visit_root_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*root_decl_node
)
4409 if (root_decl_node
->visited
) {
4413 root_decl_node
->visited
= TRUE
;
4415 switch (root_decl_node
->type
) {
4418 visit_field_class_def(ctx
, root_decl_node
->u
.field_class_def
.field_class_specifier_list
,
4419 &root_decl_node
->u
.field_class_def
.field_class_declarators
);
4421 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4422 "Cannot add field class found in root scope.");
4426 case NODE_TYPEALIAS
:
4427 ret
= visit_field_class_alias(ctx
, root_decl_node
->u
.field_class_alias
.target
,
4428 root_decl_node
->u
.field_class_alias
.alias
);
4430 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4431 "Cannot add field class alias found in root scope.");
4435 case NODE_TYPE_SPECIFIER_LIST
:
4437 struct ctf_field_class
*decl
= NULL
;
4440 * Just add the field class specifier to the root
4441 * declaration scope. Put local reference.
4443 ret
= visit_field_class_specifier_list(ctx
, root_decl_node
, &decl
);
4445 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4446 "Cannot visit root scope's field class: "
4453 ctf_field_class_destroy(decl
);
4458 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
, "Unexpected node type: node-type=%d",
4459 root_decl_node
->type
);
4468 struct ctf_visitor_generate_ir
*
4469 ctf_visitor_generate_ir_create(const struct ctf_metadata_decoder_config
*decoder_config
)
4471 struct ctf_visitor_generate_ir
*ctx
= NULL
;
4473 /* Create visitor's context */
4474 ctx
= ctx_create(decoder_config
);
4476 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
, decoder_config
->self_comp
,
4477 "Cannot create visitor's context.");
4491 void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir
*visitor
)
4493 ctx_destroy(visitor
);
4496 bt_trace_class
*ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4500 if (ctx
->trace_class
) {
4501 bt_trace_class_get_ref(ctx
->trace_class
);
4504 return ctx
->trace_class
;
4507 struct ctf_trace_class
*
4508 ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4511 BT_ASSERT_DBG(ctx
->ctf_tc
);
4515 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
4519 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
4521 switch (node
->type
) {
4524 struct ctf_node
*iter
;
4525 bool got_trace_decl
= false;
4528 * The first thing we need is the native byte order of
4529 * the trace block, because early class aliases can have
4530 * a `byte_order` attribute set to `native`. If we don't
4531 * have the native byte order yet, and we don't have any
4532 * trace block yet, then fail with EINCOMPLETE.
4534 if (ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
4535 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4536 if (got_trace_decl
) {
4537 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
4542 ret
= set_trace_byte_order(ctx
, iter
);
4544 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4545 "Cannot set trace's native byte order: "
4551 got_trace_decl
= true;
4554 if (!got_trace_decl
) {
4555 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
4561 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_LITTLE
||
4562 ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_BIG
);
4563 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4566 bt_list_for_each_entry (iter
, &node
->u
.root
.env
, siblings
) {
4567 ret
= visit_env(ctx
, iter
);
4569 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4571 "Cannot visit trace's environment (`env` block) entry: "
4578 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4581 * Visit clock blocks.
4583 bt_list_for_each_entry (iter
, &node
->u
.root
.clock
, siblings
) {
4584 ret
= visit_clock_decl(ctx
, iter
);
4586 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit clock class: ret=%d", ret
);
4591 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4594 * Visit root declarations next, as they can be used by any
4597 bt_list_for_each_entry (iter
, &node
->u
.root
.declaration_list
, siblings
) {
4598 ret
= visit_root_decl(ctx
, iter
);
4600 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit root entry: ret=%d", ret
);
4605 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4607 /* Callsite blocks are not supported */
4608 bt_list_for_each_entry (iter
, &node
->u
.root
.callsite
, siblings
) {
4609 _BT_COMP_LOGW_NODE(iter
, "\"callsite\" blocks are not supported as of this version.");
4612 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4615 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4616 ret
= visit_trace_decl(ctx
, iter
);
4618 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4619 "Cannot visit trace (`trace` block): "
4626 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4629 bt_list_for_each_entry (iter
, &node
->u
.root
.stream
, siblings
) {
4630 ret
= visit_stream_decl(ctx
, iter
);
4632 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit stream class: ret=%d", ret
);
4637 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4640 bt_list_for_each_entry (iter
, &node
->u
.root
.event
, siblings
) {
4641 ret
= visit_event_decl(ctx
, iter
);
4643 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit event class: ret=%d", ret
);
4648 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4652 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected node type: node-type=%d", node
->type
);
4657 /* Update default clock classes */
4658 ret
= ctf_trace_class_update_default_clock_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4664 /* Update trace class meanings */
4665 ret
= ctf_trace_class_update_meanings(ctx
->ctf_tc
);
4671 /* Update stream class configuration */
4672 ret
= ctf_trace_class_update_stream_class_config(ctx
->ctf_tc
);
4678 /* Update text arrays and sequences */
4679 ret
= ctf_trace_class_update_text_array_sequence(ctx
->ctf_tc
);
4685 /* Update structure/array/sequence alignments */
4686 ret
= ctf_trace_class_update_alignments(ctx
->ctf_tc
);
4692 /* Resolve sequence lengths and variant tags */
4693 ret
= ctf_trace_class_resolve_field_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4699 if (ctx
->trace_class
) {
4701 * Update "in IR" for field classes.
4703 * If we have no IR trace class, then we'll have no way
4704 * to create IR fields anyway, so we leave all the
4705 * `in_ir` members false.
4707 ret
= ctf_trace_class_update_in_ir(ctx
->ctf_tc
);
4714 /* Update saved value indexes */
4715 ret
= ctf_trace_class_update_value_storing_indexes(ctx
->ctf_tc
);
4721 /* Validate what we have so far */
4722 ret
= ctf_trace_class_validate(ctx
->ctf_tc
, &ctx
->log_cfg
);
4729 * If there are fields which are not related to the CTF format
4730 * itself in the packet header and in event header field
4731 * classes, warn about it because they are never translated.
4733 ctf_trace_class_warn_meaningless_header_fields(ctx
->ctf_tc
, &ctx
->log_cfg
);
4735 if (ctx
->trace_class
) {
4736 /* Copy new CTF metadata -> new IR metadata */
4737 ret
= ctf_trace_class_translate(ctx
->log_cfg
.self_comp
, ctx
->trace_class
, ctx
->ctf_tc
);