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).
22 #include <babeltrace2/babeltrace.h>
24 #define BT_COMP_LOG_SELF_COMP (ctx->log_cfg.self_comp)
25 #define BT_COMP_LOG_SELF_COMP_CLASS (ctx->log_cfg.self_comp_class)
26 #define BT_LOG_OUTPUT_LEVEL (ctx->log_cfg.log_level)
27 #define BT_LOG_TAG "PLUGIN/CTF/META/IR-VISITOR"
28 #include "logging.hpp"
29 #include "logging/comp-logging.h"
31 #include "common/assert.h"
32 #include "common/common.h"
33 #include "common/uuid.h"
34 #include "compat/endian.h"
37 #include "ctf-meta-visitors.hpp"
38 #include "ctf-meta.hpp"
39 #include "decoder.hpp"
40 #include "scanner.hpp"
42 /* Bit value (left shift) */
43 #define _BV(_val) (1 << (_val))
45 /* Bit is set in a set of bits */
46 #define _IS_SET(_set, _mask) (*(_set) & (_mask))
48 /* Set bit in a set of bits */
49 #define _SET(_set, _mask) (*(_set) |= (_mask))
51 /* Try to push scope, or go to the `error` label */
52 #define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
54 ret = ctx_push_scope(ctx); \
56 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot push scope."); \
61 /* Bits for verifying existing attributes in various declarations */
64 _CLOCK_NAME_SET
= _BV(0),
65 _CLOCK_UUID_SET
= _BV(1),
66 _CLOCK_FREQ_SET
= _BV(2),
67 _CLOCK_PRECISION_SET
= _BV(3),
68 _CLOCK_OFFSET_S_SET
= _BV(4),
69 _CLOCK_OFFSET_SET
= _BV(5),
70 _CLOCK_ABSOLUTE_SET
= _BV(6),
71 _CLOCK_DESCRIPTION_SET
= _BV(7),
76 _INTEGER_ALIGN_SET
= _BV(0),
77 _INTEGER_SIZE_SET
= _BV(1),
78 _INTEGER_BASE_SET
= _BV(2),
79 _INTEGER_ENCODING_SET
= _BV(3),
80 _INTEGER_BYTE_ORDER_SET
= _BV(4),
81 _INTEGER_SIGNED_SET
= _BV(5),
82 _INTEGER_MAP_SET
= _BV(6),
87 _FLOAT_ALIGN_SET
= _BV(0),
88 _FLOAT_MANT_DIG_SET
= _BV(1),
89 _FLOAT_EXP_DIG_SET
= _BV(2),
90 _FLOAT_BYTE_ORDER_SET
= _BV(3),
95 _STRING_ENCODING_SET
= _BV(0),
100 _TRACE_MINOR_SET
= _BV(0),
101 _TRACE_MAJOR_SET
= _BV(1),
102 _TRACE_BYTE_ORDER_SET
= _BV(2),
103 _TRACE_UUID_SET
= _BV(3),
104 _TRACE_PACKET_HEADER_SET
= _BV(4),
109 _STREAM_ID_SET
= _BV(0),
110 _STREAM_PACKET_CONTEXT_SET
= _BV(1),
111 _STREAM_EVENT_HEADER_SET
= _BV(2),
112 _STREAM_EVENT_CONTEXT_SET
= _BV(3),
117 _EVENT_NAME_SET
= _BV(0),
118 _EVENT_ID_SET
= _BV(1),
119 _EVENT_MODEL_EMF_URI_SET
= _BV(2),
120 _EVENT_STREAM_ID_SET
= _BV(3),
121 _EVENT_LOG_LEVEL_SET
= _BV(4),
122 _EVENT_CONTEXT_SET
= _BV(5),
123 _EVENT_FIELDS_SET
= _BV(6),
132 LOG_LEVEL_WARNING
= 4,
133 LOG_LEVEL_NOTICE
= 5,
135 LOG_LEVEL_DEBUG_SYSTEM
= 7,
136 LOG_LEVEL_DEBUG_PROGRAM
= 8,
137 LOG_LEVEL_DEBUG_PROCESS
= 9,
138 LOG_LEVEL_DEBUG_MODULE
= 10,
139 LOG_LEVEL_DEBUG_UNIT
= 11,
140 LOG_LEVEL_DEBUG_FUNCTION
= 12,
141 LOG_LEVEL_DEBUG_LINE
= 13,
142 LOG_LEVEL_DEBUG
= 14,
146 /* Prefixes of class aliases */
147 #define _PREFIX_ALIAS 'a'
148 #define _PREFIX_ENUM 'e'
149 #define _PREFIX_STRUCT 's'
150 #define _PREFIX_VARIANT 'v'
152 /* First entry in a BT list */
153 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) bt_list_entry((_ptr)->next, _class, _member)
155 #define _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \
156 _BT_COMP_LOGE_APPEND_CAUSE_LINENO( \
157 (_node)->lineno, "Duplicate attribute in %s: attr-name=\"%s\"", _entity, _attr)
159 #define _BT_COMP_LOGE_NODE(_node, _msg, args...) _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ##args)
161 #define _BT_COMP_LOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
162 _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, _msg, ##args)
164 #define _BT_COMP_LOGW_NODE(_node, _msg, args...) _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ##args)
166 #define _BT_COMP_LOGT_NODE(_node, _msg, args...) _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ##args)
169 * Declaration scope of a visitor context. This represents a TSDL
170 * lexical scope, so that aliases and named structures, variants,
171 * and enumerations may be registered and looked up hierarchically.
173 struct ctx_decl_scope
176 * Alias name to field class.
178 * GQuark -> struct ctf_field_class * (owned by this)
180 GHashTable
*decl_map
;
182 /* Parent scope; NULL if this is the root declaration scope */
183 struct ctx_decl_scope
*parent_scope
;
187 * Visitor context (private).
189 struct ctf_visitor_generate_ir
191 struct meta_log_config log_cfg
;
193 /* Trace IR trace class being filled (owned by this) */
194 bt_trace_class
*trace_class
;
196 /* CTF meta trace being filled (owned by this) */
197 struct ctf_trace_class
*ctf_tc
;
199 /* Current declaration scope (top of the stack) (owned by this) */
200 struct ctx_decl_scope
*current_scope
;
202 /* True if trace declaration is visited */
203 bool is_trace_visited
;
205 /* True if this is an LTTng trace */
208 /* Config passed by the user */
209 struct ctf_metadata_decoder_config decoder_config
;
215 struct ctf_visitor_generate_ir
;
218 * Creates a new declaration scope.
220 * @param par_scope Parent scope (NULL if creating a root scope)
221 * @returns New declaration scope, or NULL on error
223 static struct ctx_decl_scope
*ctx_decl_scope_create(struct ctf_visitor_generate_ir
*ctx
,
224 struct ctx_decl_scope
*par_scope
)
226 struct ctx_decl_scope
*scope
;
228 scope
= g_new(struct ctx_decl_scope
, 1);
230 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate one declaration scope.");
234 scope
->decl_map
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
,
235 (GDestroyNotify
) ctf_field_class_destroy
);
236 scope
->parent_scope
= par_scope
;
243 * Destroys a declaration scope.
245 * This function does not destroy the parent scope.
247 * @param scope Scope to destroy
249 static void ctx_decl_scope_destroy(struct ctx_decl_scope
*scope
)
255 g_hash_table_destroy(scope
->decl_map
);
263 * Returns the GQuark of a prefixed alias.
265 * @param prefix Prefix character
267 * @returns Associated GQuark, or 0 on error
269 static GQuark
get_prefixed_named_quark(char prefix
, const char *name
)
272 std::string prname
= std::string
{prefix
} + name
;
273 return g_quark_from_string(prname
.c_str());
277 * Looks up a prefixed class alias within a declaration scope.
279 * @param scope Declaration scope
280 * @param prefix Prefix character
281 * @param name Alias name
282 * @param levels Number of levels to dig into (-1 means infinite)
283 * @param copy True to return a copy
284 * @returns Declaration (owned by caller if \p copy is true),
285 * or NULL if not found
287 static struct ctf_field_class
*ctx_decl_scope_lookup_prefix_alias(struct ctx_decl_scope
*scope
,
288 char prefix
, const char *name
,
289 int levels
, bool copy
)
293 struct ctf_field_class
*decl
= NULL
;
294 struct ctx_decl_scope
*cur_scope
= scope
;
298 qname
= get_prefixed_named_quark(prefix
, name
);
307 while (cur_scope
&& cur_levels
< levels
) {
308 decl
= (ctf_field_class
*) g_hash_table_lookup(cur_scope
->decl_map
,
309 (gconstpointer
) GUINT_TO_POINTER(qname
));
311 /* Caller's reference */
313 decl
= ctf_field_class_copy(decl
);
320 cur_scope
= cur_scope
->parent_scope
;
329 * Looks up a class alias within a declaration scope.
331 * @param scope Declaration scope
332 * @param name Alias name
333 * @param levels Number of levels to dig into (-1 means infinite)
334 * @param copy True to return a copy
335 * @returns Declaration (owned by caller if \p copy is true),
336 * or NULL if not found
338 static struct ctf_field_class
*ctx_decl_scope_lookup_alias(struct ctx_decl_scope
*scope
,
339 const char *name
, int levels
, bool copy
)
341 return ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ALIAS
, name
, levels
, copy
);
345 * Looks up an enumeration within a declaration scope.
347 * @param scope Declaration scope
348 * @param name Enumeration name
349 * @param levels Number of levels to dig into (-1 means infinite)
350 * @param copy True to return a copy
351 * @returns Declaration (owned by caller if \p copy is true),
352 * or NULL if not found
354 static struct ctf_field_class_enum
*
355 ctx_decl_scope_lookup_enum(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
357 return ctf_field_class_as_enum(
358 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ENUM
, name
, levels
, copy
));
362 * Looks up a structure within a declaration scope.
364 * @param scope Declaration scope
365 * @param name Structure name
366 * @param levels Number of levels to dig into (-1 means infinite)
367 * @param copy True to return a copy
368 * @returns Declaration (owned by caller if \p copy is true),
369 * or NULL if not found
371 static struct ctf_field_class_struct
*
372 ctx_decl_scope_lookup_struct(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
374 return ctf_field_class_as_struct(
375 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_STRUCT
, name
, levels
, copy
));
379 * Looks up a variant within a declaration scope.
381 * @param scope Declaration scope
382 * @param name Variant name
383 * @param levels Number of levels to dig into (-1 means infinite)
384 * @param copy True to return a copy
385 * @returns Declaration (owned by caller if \p copy is true),
386 * or NULL if not found
388 static struct ctf_field_class_variant
*
389 ctx_decl_scope_lookup_variant(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
391 return ctf_field_class_as_variant(
392 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_VARIANT
, name
, levels
, copy
));
396 * Registers a prefixed class alias within a declaration scope.
398 * @param scope Declaration scope
399 * @param prefix Prefix character
400 * @param name Alias name (non-NULL)
401 * @param decl Field class to register (copied)
402 * @returns 0 if registration went okay, negative value otherwise
404 static int ctx_decl_scope_register_prefix_alias(struct ctx_decl_scope
*scope
, char prefix
,
405 const char *name
, struct ctf_field_class
*decl
)
413 qname
= get_prefixed_named_quark(prefix
, name
);
419 /* Make sure alias does not exist in local scope */
420 if (ctx_decl_scope_lookup_prefix_alias(scope
, prefix
, name
, 1, false)) {
425 decl
= ctf_field_class_copy(decl
);
427 g_hash_table_insert(scope
->decl_map
, GUINT_TO_POINTER(qname
), decl
);
434 * Registers a class alias within a declaration scope.
436 * @param scope Declaration scope
437 * @param name Alias name (non-NULL)
438 * @param decl Field class to register (copied)
439 * @returns 0 if registration went okay, negative value otherwise
441 static int ctx_decl_scope_register_alias(struct ctx_decl_scope
*scope
, const char *name
,
442 struct ctf_field_class
*decl
)
444 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ALIAS
, name
, decl
);
448 * Registers an enumeration declaration within a declaration scope.
450 * @param scope Declaration scope
451 * @param name Enumeration name (non-NULL)
452 * @param decl Enumeration field class to register (copied)
453 * @returns 0 if registration went okay, negative value otherwise
455 static int ctx_decl_scope_register_enum(struct ctx_decl_scope
*scope
, const char *name
,
456 struct ctf_field_class_enum
*decl
)
458 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ENUM
, name
, &decl
->base
.base
.base
);
462 * Registers a structure declaration within a declaration scope.
464 * @param scope Declaration scope
465 * @param name Structure name (non-NULL)
466 * @param decl Structure field class to register (copied)
467 * @returns 0 if registration went okay, negative value otherwise
469 static int ctx_decl_scope_register_struct(struct ctx_decl_scope
*scope
, const char *name
,
470 struct ctf_field_class_struct
*decl
)
472 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_STRUCT
, name
, &decl
->base
);
476 * Registers a variant declaration within a declaration scope.
478 * @param scope Declaration scope
479 * @param name Variant name (non-NULL)
480 * @param decl Variant field class to register
481 * @returns 0 if registration went okay, negative value otherwise
483 static int ctx_decl_scope_register_variant(struct ctx_decl_scope
*scope
, const char *name
,
484 struct ctf_field_class_variant
*decl
)
486 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_VARIANT
, name
, &decl
->base
);
490 * Destroys a visitor context.
492 * @param ctx Visitor context to destroy
494 static void ctx_destroy(struct ctf_visitor_generate_ir
*ctx
)
496 struct ctx_decl_scope
*scope
;
502 scope
= ctx
->current_scope
;
505 * Destroy all scopes, from current one to the root scope.
508 struct ctx_decl_scope
*parent_scope
= scope
->parent_scope
;
510 ctx_decl_scope_destroy(scope
);
511 scope
= parent_scope
;
514 bt_trace_class_put_ref(ctx
->trace_class
);
517 ctf_trace_class_destroy(ctx
->ctf_tc
);
527 * Creates a new visitor context.
529 * @param trace Associated trace
530 * @returns New visitor context, or NULL on error
532 static struct ctf_visitor_generate_ir
*
533 ctx_create(const struct ctf_metadata_decoder_config
*decoder_config
)
535 struct ctf_visitor_generate_ir
*ctx
= NULL
;
537 BT_ASSERT(decoder_config
);
539 ctx
= g_new0(struct ctf_visitor_generate_ir
, 1);
541 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
, decoder_config
->self_comp
,
542 "Failed to allocate one visitor context.");
546 ctx
->log_cfg
.log_level
= decoder_config
->log_level
;
547 ctx
->log_cfg
.self_comp
= decoder_config
->self_comp
;
548 ctx
->log_cfg
.self_comp_class
= decoder_config
->self_comp_class
;
550 if (decoder_config
->self_comp
) {
551 ctx
->trace_class
= bt_trace_class_create(decoder_config
->self_comp
);
552 if (!ctx
->trace_class
) {
553 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create empty trace class.");
558 ctx
->ctf_tc
= ctf_trace_class_create();
560 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create CTF trace class.");
564 /* Root declaration scope */
565 ctx
->current_scope
= ctx_decl_scope_create(ctx
, NULL
);
566 if (!ctx
->current_scope
) {
567 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
571 ctx
->decoder_config
= *decoder_config
;
583 * Pushes a new declaration scope on top of a visitor context's
584 * declaration scope stack.
586 * @param ctx Visitor context
587 * @returns 0 on success, or a negative value on error
589 static int ctx_push_scope(struct ctf_visitor_generate_ir
*ctx
)
592 struct ctx_decl_scope
*new_scope
;
595 new_scope
= ctx_decl_scope_create(ctx
, ctx
->current_scope
);
597 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
602 ctx
->current_scope
= new_scope
;
608 static void ctx_pop_scope(struct ctf_visitor_generate_ir
*ctx
)
610 struct ctx_decl_scope
*parent_scope
= NULL
;
614 if (!ctx
->current_scope
) {
618 parent_scope
= ctx
->current_scope
->parent_scope
;
619 ctx_decl_scope_destroy(ctx
->current_scope
);
620 ctx
->current_scope
= parent_scope
;
626 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
627 struct ctf_node
*ts_list
,
628 struct ctf_field_class
**decl
);
630 static int is_unary_string(struct bt_list_head
*head
)
633 struct ctf_node
*node
;
635 bt_list_for_each_entry (node
, head
, siblings
) {
636 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
640 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
648 static const char *get_map_clock_name_value(struct bt_list_head
*head
)
651 struct ctf_node
*node
;
652 const char *name
= NULL
;
654 bt_list_for_each_entry (node
, head
, siblings
) {
656 int uexpr_type
= node
->u
.unary_expression
.type
;
657 int uexpr_link
= node
->u
.unary_expression
.link
;
658 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_STRING
||
659 !((uexpr_link
!= UNARY_LINK_UNKNOWN
) ^ (i
== 0));
664 /* Needs to be chained with . */
665 switch (node
->u
.unary_expression
.link
) {
668 case UNARY_ARROWLINK
:
669 case UNARY_DOTDOTDOT
:
675 src_string
= node
->u
.unary_expression
.u
.string
;
679 if (strcmp("clock", src_string
)) {
687 if (strcmp("value", src_string
)) {
692 /* Extra identifier, unknown */
705 static int is_unary_unsigned(struct bt_list_head
*head
)
708 struct ctf_node
*node
;
710 bt_list_for_each_entry (node
, head
, siblings
) {
711 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
715 if (node
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
723 static int get_unary_unsigned(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
728 struct ctf_node
*node
;
732 if (bt_list_empty(head
)) {
737 bt_list_for_each_entry (node
, head
, siblings
) {
738 int uexpr_type
= node
->u
.unary_expression
.type
;
739 int uexpr_link
= node
->u
.unary_expression
.link
;
740 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_UNSIGNED_CONSTANT
||
741 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
743 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid constant unsigned integer.");
748 *value
= node
->u
.unary_expression
.u
.unsigned_constant
;
756 static int is_unary_signed(struct bt_list_head
*head
)
759 struct ctf_node
*node
;
761 bt_list_for_each_entry (node
, head
, siblings
) {
762 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
766 if (node
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
) {
774 static int get_unary_signed(struct bt_list_head
*head
, int64_t *value
)
778 struct ctf_node
*node
;
780 bt_list_for_each_entry (node
, head
, siblings
) {
781 int uexpr_type
= node
->u
.unary_expression
.type
;
782 int uexpr_link
= node
->u
.unary_expression
.link
;
783 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
784 (uexpr_type
!= UNARY_UNSIGNED_CONSTANT
&& uexpr_type
!= UNARY_SIGNED_CONSTANT
) ||
785 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
791 switch (uexpr_type
) {
792 case UNARY_UNSIGNED_CONSTANT
:
793 *value
= (int64_t) node
->u
.unary_expression
.u
.unsigned_constant
;
795 case UNARY_SIGNED_CONSTANT
:
796 *value
= node
->u
.unary_expression
.u
.signed_constant
;
810 static int get_unary_uuid(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
813 return ctf_ast_get_unary_uuid(head
, uuid
, ctx
->log_cfg
.log_level
, ctx
->log_cfg
.self_comp
);
816 static int get_boolean(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*unary_expr
)
820 if (unary_expr
->type
!= NODE_UNARY_EXPRESSION
) {
821 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
, "Expecting unary expression: node-type=%d",
827 switch (unary_expr
->u
.unary_expression
.type
) {
828 case UNARY_UNSIGNED_CONSTANT
:
829 ret
= (unary_expr
->u
.unary_expression
.u
.unsigned_constant
!= 0);
831 case UNARY_SIGNED_CONSTANT
:
832 ret
= (unary_expr
->u
.unary_expression
.u
.signed_constant
!= 0);
836 const char *str
= unary_expr
->u
.unary_expression
.u
.string
;
838 if (strcmp(str
, "true") == 0 || strcmp(str
, "TRUE") == 0) {
840 } else if (strcmp(str
, "false") == 0 || strcmp(str
, "FALSE") == 0) {
843 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
, "Unexpected boolean value: value=\"%s\"",
851 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
852 "Unexpected unary expression type: node-type=%d",
853 unary_expr
->u
.unary_expression
.type
);
862 static enum ctf_byte_order
byte_order_from_unary_expr(struct ctf_visitor_generate_ir
*ctx
,
863 struct ctf_node
*unary_expr
)
866 enum ctf_byte_order bo
= CTF_BYTE_ORDER_UNKNOWN
;
868 if (unary_expr
->u
.unary_expression
.type
!= UNARY_STRING
) {
869 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
870 unary_expr
, "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
874 str
= unary_expr
->u
.unary_expression
.u
.string
;
876 if (strcmp(str
, "be") == 0 || strcmp(str
, "network") == 0) {
877 bo
= CTF_BYTE_ORDER_BIG
;
878 } else if (strcmp(str
, "le") == 0) {
879 bo
= CTF_BYTE_ORDER_LITTLE
;
880 } else if (strcmp(str
, "native") == 0) {
881 bo
= CTF_BYTE_ORDER_DEFAULT
;
883 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
885 "Unexpected \"byte_order\" attribute value: "
886 "expecting `be`, `le`, `network`, or `native`: value=\"%s\"",
895 static enum ctf_byte_order
get_real_byte_order(struct ctf_visitor_generate_ir
*ctx
,
896 struct ctf_node
*uexpr
)
898 enum ctf_byte_order bo
= byte_order_from_unary_expr(ctx
, uexpr
);
900 if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
901 bo
= ctx
->ctf_tc
->default_byte_order
;
907 static int is_align_valid(uint64_t align
)
909 return (align
!= 0) && !(align
& (align
- UINT64_C(1)));
912 static int get_class_specifier_name(struct ctf_visitor_generate_ir
*ctx
,
913 struct ctf_node
*cls_specifier
, GString
*str
)
917 if (cls_specifier
->type
!= NODE_TYPE_SPECIFIER
) {
918 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
, "Unexpected node type: node-type=%d",
919 cls_specifier
->type
);
924 switch (cls_specifier
->u
.field_class_specifier
.type
) {
926 g_string_append(str
, "void");
929 g_string_append(str
, "char");
932 g_string_append(str
, "short");
935 g_string_append(str
, "int");
938 g_string_append(str
, "long");
941 g_string_append(str
, "float");
943 case TYPESPEC_DOUBLE
:
944 g_string_append(str
, "double");
946 case TYPESPEC_SIGNED
:
947 g_string_append(str
, "signed");
949 case TYPESPEC_UNSIGNED
:
950 g_string_append(str
, "unsigned");
953 g_string_append(str
, "bool");
955 case TYPESPEC_COMPLEX
:
956 g_string_append(str
, "_Complex");
958 case TYPESPEC_IMAGINARY
:
959 g_string_append(str
, "_Imaginary");
962 g_string_append(str
, "const");
964 case TYPESPEC_ID_TYPE
:
965 if (cls_specifier
->u
.field_class_specifier
.id_type
) {
966 g_string_append(str
, cls_specifier
->u
.field_class_specifier
.id_type
);
969 case TYPESPEC_STRUCT
:
971 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
973 if (!node
->u
._struct
.name
) {
974 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty structure field class name.");
979 g_string_append(str
, "struct ");
980 g_string_append(str
, node
->u
._struct
.name
);
983 case TYPESPEC_VARIANT
:
985 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
987 if (!node
->u
.variant
.name
) {
988 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty variant field class name.");
993 g_string_append(str
, "variant ");
994 g_string_append(str
, node
->u
.variant
.name
);
999 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1001 if (!node
->u
._enum
.enum_id
) {
1002 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1003 node
, "Unexpected empty enumeration field class (`enum`) name.");
1008 g_string_append(str
, "enum ");
1009 g_string_append(str
, node
->u
._enum
.enum_id
);
1012 case TYPESPEC_FLOATING_POINT
:
1013 case TYPESPEC_INTEGER
:
1014 case TYPESPEC_STRING
:
1016 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
->u
.field_class_specifier
.node
,
1017 "Unexpected field class specifier type: %d",
1018 cls_specifier
->u
.field_class_specifier
.type
);
1027 static int get_class_specifier_list_name(struct ctf_visitor_generate_ir
*ctx
,
1028 struct ctf_node
*cls_specifier_list
, GString
*str
)
1031 struct ctf_node
*iter
;
1032 int alias_item_nr
= 0;
1033 struct bt_list_head
*head
= &cls_specifier_list
->u
.field_class_specifier_list
.head
;
1035 bt_list_for_each_entry (iter
, head
, siblings
) {
1036 if (alias_item_nr
!= 0) {
1037 g_string_append(str
, " ");
1041 ret
= get_class_specifier_name(ctx
, iter
, str
);
1051 static GQuark
create_class_alias_identifier(struct ctf_visitor_generate_ir
*ctx
,
1052 struct ctf_node
*cls_specifier_list
,
1053 struct ctf_node
*node_field_class_declarator
)
1059 struct ctf_node
*iter
;
1060 struct bt_list_head
*pointers
= &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1062 str
= g_string_new("");
1063 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
1065 g_string_free(str
, TRUE
);
1069 bt_list_for_each_entry (iter
, pointers
, siblings
) {
1070 g_string_append(str
, " *");
1072 if (iter
->u
.pointer
.const_qualifier
) {
1073 g_string_append(str
, " const");
1077 str_c
= g_string_free(str
, FALSE
);
1078 qalias
= g_quark_from_string(str_c
);
1085 static int visit_field_class_declarator(struct ctf_visitor_generate_ir
*ctx
,
1086 struct ctf_node
*cls_specifier_list
, GQuark
*field_name
,
1087 struct ctf_node
*node_field_class_declarator
,
1088 struct ctf_field_class
**field_decl
,
1089 struct ctf_field_class
*nested_decl
)
1092 * During this whole function, nested_decl is always OURS,
1093 * whereas field_decl is an output which we create, but
1094 * belongs to the caller (it is moved).
1099 /* Validate field class declarator node */
1100 if (node_field_class_declarator
) {
1101 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_UNKNOWN
) {
1102 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1103 node_field_class_declarator
, "Unexpected field class declarator type: type=%d",
1104 node_field_class_declarator
->u
.field_class_declarator
.type
);
1109 /* TODO: GCC bitfields not supported yet */
1110 if (node_field_class_declarator
->u
.field_class_declarator
.bitfield_len
!= NULL
) {
1111 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1112 "GCC bitfields are not supported as of this version.");
1118 /* Find the right nested declaration if not provided */
1120 if (node_field_class_declarator
&&
1121 !bt_list_empty(&node_field_class_declarator
->u
.field_class_declarator
.pointers
)) {
1125 * If we have a pointer declarator, it HAS to
1126 * be present in the field class aliases (else
1130 create_class_alias_identifier(ctx
, cls_specifier_list
, node_field_class_declarator
);
1131 nested_decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, g_quark_to_string(qalias
),
1134 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1135 "Cannot find class alias: name=\"%s\"",
1136 g_quark_to_string(qalias
));
1141 if (nested_decl
->type
== CTF_FIELD_CLASS_TYPE_INT
) {
1142 /* Pointer: force integer's base to 16 */
1143 struct ctf_field_class_int
*int_fc
= ctf_field_class_as_int(nested_decl
);
1145 int_fc
->disp_base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
1148 ret
= visit_field_class_specifier_list(ctx
, cls_specifier_list
, &nested_decl
);
1150 BT_ASSERT(!nested_decl
);
1156 BT_ASSERT(nested_decl
);
1158 if (!node_field_class_declarator
) {
1159 *field_decl
= nested_decl
;
1164 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_ID
) {
1165 if (node_field_class_declarator
->u
.field_class_declarator
.u
.id
) {
1166 const char *id
= node_field_class_declarator
->u
.field_class_declarator
.u
.id
;
1168 *field_name
= g_quark_from_string(id
);
1173 *field_decl
= nested_decl
;
1177 struct ctf_node
*first
;
1178 struct ctf_field_class
*decl
= NULL
;
1179 struct ctf_field_class
*outer_field_decl
= NULL
;
1180 struct bt_list_head
*length
=
1181 &node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.length
;
1183 /* Create array/sequence, pass nested_decl as child */
1184 if (bt_list_empty(length
)) {
1185 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1186 "Expecting length field reference or value.");
1191 first
= _BT_LIST_FIRST_ENTRY(length
, struct ctf_node
, siblings
);
1192 if (first
->type
!= NODE_UNARY_EXPRESSION
) {
1193 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type=%d",
1199 switch (first
->u
.unary_expression
.type
) {
1200 case UNARY_UNSIGNED_CONSTANT
:
1202 struct ctf_field_class_array
*array_decl
= NULL
;
1204 array_decl
= ctf_field_class_array_create();
1205 BT_ASSERT(array_decl
);
1206 array_decl
->length
= first
->u
.unary_expression
.u
.unsigned_constant
;
1207 array_decl
->base
.elem_fc
= nested_decl
;
1209 decl
= &array_decl
->base
.base
;
1214 /* Lookup unsigned integer definition, create seq. */
1215 struct ctf_field_class_sequence
*seq_decl
= NULL
;
1216 char *length_name
= ctf_ast_concatenate_unary_strings(length
);
1219 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1220 "Cannot concatenate unary strings.");
1225 if (strncmp(length_name
, "env.", 4) == 0) {
1226 /* This is, in fact, an array */
1227 const char *env_entry_name
= &length_name
[4];
1228 struct ctf_trace_class_env_entry
*env_entry
=
1229 ctf_trace_class_borrow_env_entry_by_name(ctx
->ctf_tc
, env_entry_name
);
1230 struct ctf_field_class_array
*array_decl
;
1233 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1234 "Cannot find environment entry: "
1241 if (env_entry
->type
!= CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
) {
1242 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1243 "Wrong environment entry type "
1244 "(expecting integer): "
1251 if (env_entry
->value
.i
< 0) {
1252 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1253 "Invalid, negative array length: "
1254 "env-entry-name=\"%s\", "
1256 env_entry_name
, env_entry
->value
.i
);
1261 array_decl
= ctf_field_class_array_create();
1262 BT_ASSERT(array_decl
);
1263 array_decl
->length
= (uint64_t) env_entry
->value
.i
;
1264 array_decl
->base
.elem_fc
= nested_decl
;
1266 decl
= &array_decl
->base
.base
;
1268 seq_decl
= ctf_field_class_sequence_create();
1269 BT_ASSERT(seq_decl
);
1270 seq_decl
->base
.elem_fc
= nested_decl
;
1272 g_string_assign(seq_decl
->length_ref
, length_name
);
1273 decl
= &seq_decl
->base
.base
;
1276 g_free(length_name
);
1284 BT_ASSERT(!nested_decl
);
1286 BT_ASSERT(!*field_decl
);
1289 * At this point, we found the next nested declaration.
1290 * We currently own this (and lost the ownership of
1291 * nested_decl in the meantime). Pass this next
1292 * nested declaration as the content of the outer
1293 * container, MOVING its ownership.
1295 ret
= visit_field_class_declarator(
1296 ctx
, cls_specifier_list
, field_name
,
1297 node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.field_class_declarator
,
1298 &outer_field_decl
, decl
);
1301 BT_ASSERT(!outer_field_decl
);
1306 BT_ASSERT(outer_field_decl
);
1307 *field_decl
= outer_field_decl
;
1308 outer_field_decl
= NULL
;
1311 BT_ASSERT(*field_decl
);
1315 ctf_field_class_destroy(*field_decl
);
1323 ctf_field_class_destroy(nested_decl
);
1328 static int visit_struct_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1329 struct ctf_field_class_struct
*struct_decl
,
1330 struct ctf_node
*cls_specifier_list
,
1331 struct bt_list_head
*field_class_declarators
)
1334 struct ctf_node
*iter
;
1335 struct ctf_field_class
*field_decl
= NULL
;
1337 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1340 const char *field_name
;
1342 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1345 BT_ASSERT(!field_decl
);
1346 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1347 "Cannot visit field class declarator: ret=%d", ret
);
1351 BT_ASSERT(field_decl
);
1352 field_name
= g_quark_to_string(qfield_name
);
1354 /* Check if field with same name already exists */
1355 if (ctf_field_class_struct_borrow_member_by_name(struct_decl
, field_name
)) {
1356 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1357 "Duplicate field in structure field class: "
1358 "field-name=\"%s\"",
1364 /* Add field to structure */
1365 ctf_field_class_struct_append_member(struct_decl
, field_name
, field_decl
);
1372 ctf_field_class_destroy(field_decl
);
1377 static int visit_variant_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1378 struct ctf_field_class_variant
*variant_decl
,
1379 struct ctf_node
*cls_specifier_list
,
1380 struct bt_list_head
*field_class_declarators
)
1383 struct ctf_node
*iter
;
1384 struct ctf_field_class
*field_decl
= NULL
;
1386 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1389 const char *field_name
;
1391 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1394 BT_ASSERT(!field_decl
);
1395 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1396 "Cannot visit field class declarator: ret=%d", ret
);
1400 BT_ASSERT(field_decl
);
1401 field_name
= g_quark_to_string(qfield_name
);
1403 /* Check if field with same name already exists */
1404 if (ctf_field_class_variant_borrow_option_by_name(variant_decl
, field_name
)) {
1405 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1406 "Duplicate field in variant field class: "
1407 "field-name=\"%s\"",
1413 /* Add field to structure */
1414 ctf_field_class_variant_append_option(variant_decl
, field_name
, field_decl
);
1421 ctf_field_class_destroy(field_decl
);
1426 static int visit_field_class_def(struct ctf_visitor_generate_ir
*ctx
,
1427 struct ctf_node
*cls_specifier_list
,
1428 struct bt_list_head
*field_class_declarators
)
1432 struct ctf_node
*iter
;
1433 struct ctf_field_class
*class_decl
= NULL
;
1435 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1436 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qidentifier
, iter
, &class_decl
,
1439 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit field class declarator: ret=%d",
1445 /* Do not allow field class def and alias of untagged variants */
1446 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1447 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1449 if (var_fc
->tag_path
.path
->len
== 0) {
1450 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1451 iter
, "Type definition of untagged variant field class is not allowed.");
1457 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qidentifier
),
1460 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot register field class alias: name=\"%s\"",
1461 g_quark_to_string(qidentifier
));
1467 ctf_field_class_destroy(class_decl
);
1472 static int visit_field_class_alias(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*target
,
1473 struct ctf_node
*alias
)
1477 struct ctf_node
*node
;
1478 GQuark qdummy_field_name
;
1479 struct ctf_field_class
*class_decl
= NULL
;
1481 /* Create target field class */
1482 if (bt_list_empty(&target
->u
.field_class_alias_target
.field_class_declarators
)) {
1485 node
= _BT_LIST_FIRST_ENTRY(&target
->u
.field_class_alias_target
.field_class_declarators
,
1486 struct ctf_node
, siblings
);
1489 ret
= visit_field_class_declarator(
1490 ctx
, target
->u
.field_class_alias_target
.field_class_specifier_list
, &qdummy_field_name
,
1491 node
, &class_decl
, NULL
);
1493 BT_ASSERT(!class_decl
);
1494 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot visit field class declarator: ret=%d", ret
);
1498 /* Do not allow field class def and alias of untagged variants */
1499 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1500 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1502 if (var_fc
->tag_path
.path
->len
== 0) {
1503 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1504 target
, "Type definition of untagged variant field class is not allowed.");
1511 * The semantic validator does not check whether the target is
1512 * abstract or not (if it has an identifier). Check it here.
1514 if (qdummy_field_name
!= 0) {
1515 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target
, "Expecting empty identifier: id=\"%s\"",
1516 g_quark_to_string(qdummy_field_name
));
1521 /* Create alias identifier */
1522 node
= _BT_LIST_FIRST_ENTRY(&alias
->u
.field_class_alias_name
.field_class_declarators
,
1523 struct ctf_node
, siblings
);
1524 qalias
= create_class_alias_identifier(
1525 ctx
, alias
->u
.field_class_alias_name
.field_class_specifier_list
, node
);
1526 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qalias
), class_decl
);
1528 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot register class alias: name=\"%s\"",
1529 g_quark_to_string(qalias
));
1534 ctf_field_class_destroy(class_decl
);
1539 static int visit_struct_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
1540 struct ctf_field_class_struct
*struct_decl
)
1544 switch (entry_node
->type
) {
1546 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1547 &entry_node
->u
.field_class_def
.field_class_declarators
);
1549 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1550 entry_node
, "Cannot add field class found in structure field class: ret=%d", ret
);
1554 case NODE_TYPEALIAS
:
1555 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1556 entry_node
->u
.field_class_alias
.alias
);
1558 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1559 entry_node
, "Cannot add field class alias found in structure field class: ret=%d",
1564 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1566 ret
= visit_struct_decl_field(
1568 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1569 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1575 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
1585 static int visit_variant_decl_entry(struct ctf_visitor_generate_ir
*ctx
,
1586 struct ctf_node
*entry_node
,
1587 struct ctf_field_class_variant
*variant_decl
)
1591 switch (entry_node
->type
) {
1593 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1594 &entry_node
->u
.field_class_def
.field_class_declarators
);
1596 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1597 entry_node
, "Cannot add field class found in variant field class: ret=%d", ret
);
1601 case NODE_TYPEALIAS
:
1602 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1603 entry_node
->u
.field_class_alias
.alias
);
1605 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1606 entry_node
, "Cannot add field class alias found in variant field class: ret=%d",
1611 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1613 ret
= visit_variant_decl_field(
1615 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1616 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1622 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
1632 static int visit_struct_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1633 struct bt_list_head
*decl_list
, int has_body
,
1634 struct bt_list_head
*min_align
,
1635 struct ctf_field_class_struct
**struct_decl
)
1639 BT_ASSERT(struct_decl
);
1640 *struct_decl
= NULL
;
1642 /* For named struct (without body), lookup in declaration scope */
1645 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1646 "Bodyless structure field class: missing name.");
1651 *struct_decl
= ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, -1, true);
1652 if (!*struct_decl
) {
1653 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1654 "Cannot find structure field class: name=\"struct %s\"", name
);
1659 struct ctf_node
*entry_node
;
1660 uint64_t min_align_value
= 0;
1663 if (ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, 1, false)) {
1664 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1665 "Structure field class already declared in local scope: "
1666 "name=\"struct %s\"",
1673 if (!bt_list_empty(min_align
)) {
1674 ret
= get_unary_unsigned(ctx
, min_align
, &min_align_value
);
1676 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1677 "Unexpected unary expression for structure field class's `align` attribute: "
1684 *struct_decl
= ctf_field_class_struct_create();
1685 BT_ASSERT(*struct_decl
);
1687 if (min_align_value
!= 0) {
1688 (*struct_decl
)->base
.alignment
= min_align_value
;
1691 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1693 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1694 ret
= visit_struct_decl_entry(ctx
, entry_node
, *struct_decl
);
1696 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1697 "Cannot visit structure field class entry: "
1708 ret
= ctx_decl_scope_register_struct(ctx
->current_scope
, name
, *struct_decl
);
1710 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1711 "Cannot register structure field class in declaration scope: "
1712 "name=\"struct %s\", ret=%d",
1722 ctf_field_class_destroy(&(*struct_decl
)->base
);
1723 *struct_decl
= NULL
;
1727 static int visit_variant_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1728 const char *tag
, struct bt_list_head
*decl_list
, int has_body
,
1729 struct ctf_field_class_variant
**variant_decl
)
1732 struct ctf_field_class_variant
*untagged_variant_decl
= NULL
;
1734 BT_ASSERT(variant_decl
);
1735 *variant_decl
= NULL
;
1737 /* For named variant (without body), lookup in declaration scope */
1740 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name.");
1745 untagged_variant_decl
= ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, -1, true);
1746 if (!untagged_variant_decl
) {
1747 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1748 "Cannot find variant field class: name=\"variant %s\"", name
);
1753 struct ctf_node
*entry_node
;
1756 if (ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, 1, false)) {
1757 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1758 "Variant field class already declared in local scope: "
1759 "name=\"variant %s\"",
1766 untagged_variant_decl
= ctf_field_class_variant_create();
1767 BT_ASSERT(untagged_variant_decl
);
1768 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1770 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1771 ret
= visit_variant_decl_entry(ctx
, entry_node
, untagged_variant_decl
);
1773 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1774 "Cannot visit variant field class entry: "
1785 ret
= ctx_decl_scope_register_variant(ctx
->current_scope
, name
, untagged_variant_decl
);
1787 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1788 "Cannot register variant field class in declaration scope: "
1789 "name=\"variant %s\", ret=%d",
1797 * If tagged, create tagged variant and return; otherwise
1798 * return untagged variant.
1801 *variant_decl
= untagged_variant_decl
;
1802 untagged_variant_decl
= NULL
;
1805 * At this point, we have a fresh untagged variant; nobody
1806 * else owns it. Set its tag now.
1808 g_string_assign(untagged_variant_decl
->tag_ref
, tag
);
1809 *variant_decl
= untagged_variant_decl
;
1810 untagged_variant_decl
= NULL
;
1813 BT_ASSERT(!untagged_variant_decl
);
1814 BT_ASSERT(*variant_decl
);
1818 ctf_field_class_destroy(&untagged_variant_decl
->base
);
1819 untagged_variant_decl
= NULL
;
1820 ctf_field_class_destroy(&(*variant_decl
)->base
);
1821 *variant_decl
= NULL
;
1835 static int visit_enum_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*enumerator
,
1836 struct ctf_field_class_enum
*enum_decl
, struct uori
*last
)
1840 struct ctf_node
*iter
;
1841 struct uori start
= {
1855 const char *label
= enumerator
->u
.enumerator
.id
;
1856 struct bt_list_head
*values
= &enumerator
->u
.enumerator
.values
;
1858 bt_list_for_each_entry (iter
, values
, siblings
) {
1859 struct uori
*target
;
1861 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
1862 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1863 "Wrong expression for enumeration field class label: "
1864 "node-type=%d, label=\"%s\"",
1876 switch (iter
->u
.unary_expression
.type
) {
1877 case UNARY_SIGNED_CONSTANT
:
1878 target
->is_signed
= true;
1879 target
->value
.i
= iter
->u
.unary_expression
.u
.signed_constant
;
1881 case UNARY_UNSIGNED_CONSTANT
:
1882 target
->is_signed
= false;
1883 target
->value
.u
= iter
->u
.unary_expression
.u
.unsigned_constant
;
1886 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1887 "Invalid enumeration field class entry: "
1888 "expecting constant signed or unsigned integer: "
1889 "node-type=%d, label=\"%s\"",
1890 iter
->u
.unary_expression
.type
, label
);
1896 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1897 iter
, "Invalid enumeration field class entry: label=\"%s\"", label
);
1913 if (end
.is_signed
) {
1914 last
->value
.i
= end
.value
.i
+ 1;
1916 last
->value
.u
= end
.value
.u
+ 1;
1919 ctf_field_class_enum_map_range(enum_decl
, label
, start
.value
.u
, end
.value
.u
);
1926 static int visit_enum_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1927 struct ctf_node
*container_cls
, struct bt_list_head
*enumerator_list
,
1928 int has_body
, struct ctf_field_class_enum
**enum_decl
)
1932 struct ctf_field_class_int
*integer_decl
= NULL
;
1934 BT_ASSERT(enum_decl
);
1937 /* For named enum (without body), lookup in declaration scope */
1940 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1941 "Bodyless enumeration field class: missing name.");
1946 *enum_decl
= ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, -1, true);
1948 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: "
1955 struct ctf_node
*iter
;
1956 struct uori last_value
= {
1965 if (ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, 1, false)) {
1966 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1967 "Enumeration field class already declared in local scope: "
1975 if (!container_cls
) {
1976 integer_decl
= ctf_field_class_as_int(
1977 ctx_decl_scope_lookup_alias(ctx
->current_scope
, "int", -1, true));
1978 if (!integer_decl
) {
1979 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1980 "Cannot find implicit `int` field class alias for enumeration field class.");
1985 ctf_field_class
*decl
;
1987 ret
= visit_field_class_declarator(ctx
, container_cls
, &qdummy_id
, NULL
, &decl
, NULL
);
1994 integer_decl
= ctf_field_class_as_int(decl
);
1997 BT_ASSERT(integer_decl
);
1999 if (integer_decl
->base
.base
.type
!= CTF_FIELD_CLASS_TYPE_INT
) {
2000 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2001 "Container field class for enumeration field class is not an integer field class: "
2003 integer_decl
->base
.base
.type
);
2008 *enum_decl
= ctf_field_class_enum_create();
2009 BT_ASSERT(*enum_decl
);
2010 (*enum_decl
)->base
.base
.base
.alignment
= integer_decl
->base
.base
.alignment
;
2011 ctf_field_class_int_copy_content(&(*enum_decl
)->base
, integer_decl
);
2012 last_value
.is_signed
= (*enum_decl
)->base
.is_signed
;
2014 bt_list_for_each_entry (iter
, enumerator_list
, siblings
) {
2015 ret
= visit_enum_decl_entry(ctx
, iter
, *enum_decl
, &last_value
);
2017 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
2018 "Cannot visit enumeration field class entry: "
2026 ret
= ctx_decl_scope_register_enum(ctx
->current_scope
, name
, *enum_decl
);
2028 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2029 "Cannot register enumeration field class in declaration scope: "
2040 ctf_field_class_destroy(&(*enum_decl
)->base
.base
.base
);
2044 ctf_field_class_destroy(&integer_decl
->base
.base
);
2045 integer_decl
= NULL
;
2049 static int visit_field_class_specifier(struct ctf_visitor_generate_ir
*ctx
,
2050 struct ctf_node
*cls_specifier_list
,
2051 struct ctf_field_class
**decl
)
2054 GString
*str
= NULL
;
2057 str
= g_string_new("");
2058 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
2060 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2061 cls_specifier_list
, "Cannot get field class specifier list's name: ret=%d", ret
);
2065 *decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, str
->str
, -1, true);
2067 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2068 "Cannot find field class alias: name=\"%s\"", str
->str
);
2076 ctf_field_class_destroy(*decl
);
2081 g_string_free(str
, TRUE
);
2087 static int visit_integer_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2088 struct ctf_field_class_int
**integer_decl
)
2093 struct ctf_node
*expression
;
2094 uint64_t alignment
= 0, size
= 0;
2095 struct ctf_clock_class
*mapped_clock_class
= NULL
;
2096 enum ctf_encoding encoding
= CTF_ENCODING_NONE
;
2097 bt_field_class_integer_preferred_display_base base
=
2098 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2099 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2101 *integer_decl
= NULL
;
2103 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2104 struct ctf_node
*left
, *right
;
2106 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2108 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2110 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2111 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2112 left
->u
.unary_expression
.type
);
2117 if (strcmp(left
->u
.unary_expression
.u
.string
, "signed") == 0) {
2118 if (_IS_SET(&set
, _INTEGER_SIGNED_SET
)) {
2119 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "signed", "integer field class");
2124 signedness
= get_boolean(ctx
, right
);
2125 if (signedness
< 0) {
2126 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2128 "Invalid boolean value for integer field class's `signed` attribute: "
2135 _SET(&set
, _INTEGER_SIGNED_SET
);
2136 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2137 if (_IS_SET(&set
, _INTEGER_BYTE_ORDER_SET
)) {
2138 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order", "integer field class");
2143 byte_order
= get_real_byte_order(ctx
, right
);
2144 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2145 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2147 "Invalid `byte_order` attribute in integer field class: "
2154 _SET(&set
, _INTEGER_BYTE_ORDER_SET
);
2155 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "size") == 0) {
2156 if (_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2157 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "size", "integer field class");
2162 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2163 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2164 "Invalid `size` attribute in integer field class: "
2165 "expecting unsigned constant integer: "
2167 right
->u
.unary_expression
.type
);
2172 size
= right
->u
.unary_expression
.u
.unsigned_constant
;
2174 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2175 "Invalid `size` attribute in integer field class: "
2176 "expecting positive constant integer: "
2181 } else if (size
> 64) {
2182 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2184 "Invalid `size` attribute in integer field class: "
2185 "integer fields over 64 bits are not supported as of this version: "
2192 _SET(&set
, _INTEGER_SIZE_SET
);
2193 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2194 if (_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2195 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align", "integer field class");
2200 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2201 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2202 "Invalid `align` attribute in integer field class: "
2203 "expecting unsigned constant integer: "
2205 right
->u
.unary_expression
.type
);
2210 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2211 if (!is_align_valid(alignment
)) {
2212 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2213 "Invalid `align` attribute in integer field class: "
2214 "expecting power of two: "
2221 _SET(&set
, _INTEGER_ALIGN_SET
);
2222 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "base") == 0) {
2223 if (_IS_SET(&set
, _INTEGER_BASE_SET
)) {
2224 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "base", "integer field class");
2229 switch (right
->u
.unary_expression
.type
) {
2230 case UNARY_UNSIGNED_CONSTANT
:
2232 uint64_t constant
= right
->u
.unary_expression
.u
.unsigned_constant
;
2236 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2239 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2242 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2245 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2248 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2250 "Invalid `base` attribute in integer field class: "
2252 right
->u
.unary_expression
.u
.unsigned_constant
);
2261 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2263 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2265 "Unexpected unary expression for integer field class's `base` attribute.");
2270 if (strcmp(s_right
, "decimal") == 0 || strcmp(s_right
, "dec") == 0 ||
2271 strcmp(s_right
, "d") == 0 || strcmp(s_right
, "i") == 0 ||
2272 strcmp(s_right
, "u") == 0) {
2273 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2274 } else if (strcmp(s_right
, "hexadecimal") == 0 || strcmp(s_right
, "hex") == 0 ||
2275 strcmp(s_right
, "x") == 0 || strcmp(s_right
, "X") == 0 ||
2276 strcmp(s_right
, "p") == 0) {
2277 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2278 } else if (strcmp(s_right
, "octal") == 0 || strcmp(s_right
, "oct") == 0 ||
2279 strcmp(s_right
, "o") == 0) {
2280 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2281 } else if (strcmp(s_right
, "binary") == 0 || strcmp(s_right
, "b") == 0) {
2282 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2284 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2286 "Unexpected unary expression for integer field class's `base` attribute: "
2298 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2299 right
, "Invalid `base` attribute in integer field class: "
2300 "expecting unsigned constant integer or unary string.");
2305 _SET(&set
, _INTEGER_BASE_SET
);
2306 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2309 if (_IS_SET(&set
, _INTEGER_ENCODING_SET
)) {
2310 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "integer field class");
2315 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2316 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2317 right
, "Invalid `encoding` attribute in integer field class: "
2318 "expecting unary string.");
2323 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2325 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2327 "Unexpected unary expression for integer field class's `encoding` attribute.");
2332 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2333 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2334 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2335 encoding
= CTF_ENCODING_UTF8
;
2336 } else if (strcmp(s_right
, "none") == 0) {
2337 encoding
= CTF_ENCODING_NONE
;
2339 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2341 "Invalid `encoding` attribute in integer field class: "
2342 "unknown encoding: encoding=\"%s\"",
2350 _SET(&set
, _INTEGER_ENCODING_SET
);
2351 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "map") == 0) {
2352 const char *clock_name
;
2354 if (_IS_SET(&set
, _INTEGER_MAP_SET
)) {
2355 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "map", "integer field class");
2360 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2361 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2362 "Invalid `map` attribute in integer field class: "
2363 "expecting unary string.");
2368 clock_name
= get_map_clock_name_value(&expression
->u
.ctf_expression
.right
);
2371 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2374 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2376 "Unexpected unary expression for integer field class's `map` attribute.");
2381 _BT_COMP_LOGE_NODE(right
,
2382 "Invalid `map` attribute in integer field class: "
2383 "cannot find clock class at this point: name=\"%s\"",
2385 _SET(&set
, _INTEGER_MAP_SET
);
2390 mapped_clock_class
=
2391 ctf_trace_class_borrow_clock_class_by_name(ctx
->ctf_tc
, clock_name
);
2392 if (!mapped_clock_class
) {
2393 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2395 "Invalid `map` attribute in integer field class: "
2396 "cannot find clock class at this point: name=\"%s\"",
2402 _SET(&set
, _INTEGER_MAP_SET
);
2404 _BT_COMP_LOGW_NODE(left
,
2405 "Unknown attribute in integer field class: "
2407 left
->u
.unary_expression
.u
.string
);
2411 if (!_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2412 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2413 "Missing `size` attribute in integer field class.");
2418 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2419 if (size
% CHAR_BIT
) {
2420 /* Bit-packed alignment */
2423 /* Byte-packed alignment */
2424 alignment
= CHAR_BIT
;
2428 *integer_decl
= ctf_field_class_int_create();
2429 BT_ASSERT(*integer_decl
);
2430 (*integer_decl
)->base
.base
.alignment
= alignment
;
2431 (*integer_decl
)->base
.byte_order
= byte_order
;
2432 (*integer_decl
)->base
.size
= size
;
2433 (*integer_decl
)->is_signed
= (signedness
> 0);
2434 (*integer_decl
)->disp_base
= base
;
2435 (*integer_decl
)->encoding
= encoding
;
2436 (*integer_decl
)->mapped_clock_class
= mapped_clock_class
;
2440 ctf_field_class_destroy(&(*integer_decl
)->base
.base
);
2441 *integer_decl
= NULL
;
2445 static int visit_floating_point_number_decl(struct ctf_visitor_generate_ir
*ctx
,
2446 struct bt_list_head
*expressions
,
2447 struct ctf_field_class_float
**float_decl
)
2451 struct ctf_node
*expression
;
2452 uint64_t alignment
= 1, exp_dig
= 0, mant_dig
= 0;
2453 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2457 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2458 struct ctf_node
*left
, *right
;
2460 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2462 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2464 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2465 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2466 left
->u
.unary_expression
.type
);
2471 if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2472 if (_IS_SET(&set
, _FLOAT_BYTE_ORDER_SET
)) {
2473 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order",
2474 "floating point number field class");
2479 byte_order
= get_real_byte_order(ctx
, right
);
2480 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2481 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2483 "Invalid `byte_order` attribute in floating point number field class: "
2490 _SET(&set
, _FLOAT_BYTE_ORDER_SET
);
2491 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "exp_dig") == 0) {
2492 if (_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2493 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "exp_dig",
2494 "floating point number field class");
2499 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2500 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2502 "Invalid `exp_dig` attribute in floating point number field class: "
2503 "expecting unsigned constant integer: "
2505 right
->u
.unary_expression
.type
);
2510 exp_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2511 _SET(&set
, _FLOAT_EXP_DIG_SET
);
2512 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "mant_dig") == 0) {
2513 if (_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2514 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "mant_dig",
2515 "floating point number field class");
2520 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2521 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2523 "Invalid `mant_dig` attribute in floating point number field class: "
2524 "expecting unsigned constant integer: "
2526 right
->u
.unary_expression
.type
);
2531 mant_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2532 _SET(&set
, _FLOAT_MANT_DIG_SET
);
2533 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2534 if (_IS_SET(&set
, _FLOAT_ALIGN_SET
)) {
2535 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align",
2536 "floating point number field class");
2541 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2542 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2544 "Invalid `align` attribute in floating point number field class: "
2545 "expecting unsigned constant integer: "
2547 right
->u
.unary_expression
.type
);
2552 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2554 if (!is_align_valid(alignment
)) {
2555 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2557 "Invalid `align` attribute in floating point number field class: "
2558 "expecting power of two: "
2565 _SET(&set
, _FLOAT_ALIGN_SET
);
2567 _BT_COMP_LOGW_NODE(left
,
2568 "Unknown attribute in floating point number field class: "
2570 left
->u
.unary_expression
.u
.string
);
2574 if (!_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2575 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2576 "Missing `mant_dig` attribute in floating point number field class.");
2581 if (!_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2582 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2583 "Missing `exp_dig` attribute in floating point number field class.");
2588 if (mant_dig
!= 24 && mant_dig
!= 53) {
2589 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53.");
2594 if (mant_dig
== 24 && exp_dig
!= 8) {
2595 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2596 "`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2601 if (mant_dig
== 53 && exp_dig
!= 11) {
2602 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2603 "`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2608 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2609 if ((mant_dig
+ exp_dig
) % CHAR_BIT
) {
2610 /* Bit-packed alignment */
2613 /* Byte-packed alignment */
2614 alignment
= CHAR_BIT
;
2618 *float_decl
= ctf_field_class_float_create();
2619 BT_ASSERT(*float_decl
);
2620 (*float_decl
)->base
.base
.alignment
= alignment
;
2621 (*float_decl
)->base
.byte_order
= byte_order
;
2622 (*float_decl
)->base
.size
= mant_dig
+ exp_dig
;
2626 ctf_field_class_destroy(&(*float_decl
)->base
.base
);
2631 static int visit_string_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2632 struct ctf_field_class_string
**string_decl
)
2636 struct ctf_node
*expression
;
2637 enum ctf_encoding encoding
= CTF_ENCODING_UTF8
;
2639 *string_decl
= NULL
;
2641 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2642 struct ctf_node
*left
, *right
;
2644 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2646 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2648 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2649 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2650 left
->u
.unary_expression
.type
);
2655 if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2658 if (_IS_SET(&set
, _STRING_ENCODING_SET
)) {
2659 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "string field class");
2664 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2665 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2666 right
, "Invalid `encoding` attribute in string field class: "
2667 "expecting unary string.");
2672 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2674 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2676 "Unexpected unary expression for string field class's `encoding` attribute.");
2681 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2682 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2683 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2684 encoding
= CTF_ENCODING_UTF8
;
2685 } else if (strcmp(s_right
, "none") == 0) {
2686 encoding
= CTF_ENCODING_NONE
;
2688 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2690 "Invalid `encoding` attribute in string field class: "
2691 "unknown encoding: encoding=\"%s\"",
2699 _SET(&set
, _STRING_ENCODING_SET
);
2701 _BT_COMP_LOGW_NODE(left
,
2702 "Unknown attribute in string field class: "
2704 left
->u
.unary_expression
.u
.string
);
2708 *string_decl
= ctf_field_class_string_create();
2709 BT_ASSERT(*string_decl
);
2710 (*string_decl
)->encoding
= encoding
;
2714 ctf_field_class_destroy(&(*string_decl
)->base
);
2715 *string_decl
= NULL
;
2719 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
2720 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
)
2723 struct ctf_node
*first
, *node
;
2727 if (ts_list
->type
!= NODE_TYPE_SPECIFIER_LIST
) {
2728 _BT_COMP_LOGE_APPEND_CAUSE_NODE(ts_list
, "Unexpected node type: node-type=%d",
2734 first
= _BT_LIST_FIRST_ENTRY(&ts_list
->u
.field_class_specifier_list
.head
, struct ctf_node
,
2736 if (first
->type
!= NODE_TYPE_SPECIFIER
) {
2737 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type=%d", first
->type
);
2742 node
= first
->u
.field_class_specifier
.node
;
2744 switch (first
->u
.field_class_specifier
.type
) {
2745 case TYPESPEC_INTEGER
:
2747 ctf_field_class_int
*int_decl
;
2749 ret
= visit_integer_decl(ctx
, &node
->u
.integer
.expressions
, &int_decl
);
2751 BT_ASSERT(!int_decl
);
2755 *decl
= &int_decl
->base
.base
;
2758 case TYPESPEC_FLOATING_POINT
:
2760 ctf_field_class_float
*float_decl
;
2763 visit_floating_point_number_decl(ctx
, &node
->u
.floating_point
.expressions
, &float_decl
);
2765 BT_ASSERT(!float_decl
);
2769 *decl
= &float_decl
->base
.base
;
2772 case TYPESPEC_STRING
:
2774 ctf_field_class_string
*string_decl
;
2776 ret
= visit_string_decl(ctx
, &node
->u
.string
.expressions
, &string_decl
);
2778 BT_ASSERT(!string_decl
);
2782 *decl
= &string_decl
->base
;
2785 case TYPESPEC_STRUCT
:
2787 ctf_field_class_struct
*struct_decl
;
2789 ret
= visit_struct_decl(ctx
, node
->u
._struct
.name
, &node
->u
._struct
.declaration_list
,
2790 node
->u
._struct
.has_body
, &node
->u
._struct
.min_align
, &struct_decl
);
2792 BT_ASSERT(!struct_decl
);
2796 *decl
= &struct_decl
->base
;
2799 case TYPESPEC_VARIANT
:
2801 ctf_field_class_variant
*variant_decl
;
2803 ret
= visit_variant_decl(ctx
, node
->u
.variant
.name
, node
->u
.variant
.choice
,
2804 &node
->u
.variant
.declaration_list
, node
->u
.variant
.has_body
,
2807 BT_ASSERT(!variant_decl
);
2811 *decl
= &variant_decl
->base
;
2816 ctf_field_class_enum
*enum_decl
;
2818 ret
= visit_enum_decl(ctx
, node
->u
._enum
.enum_id
, node
->u
._enum
.container_field_class
,
2819 &node
->u
._enum
.enumerator_list
, node
->u
._enum
.has_body
, &enum_decl
);
2821 BT_ASSERT(!enum_decl
);
2825 *decl
= &enum_decl
->base
.base
.base
;
2830 case TYPESPEC_SHORT
:
2833 case TYPESPEC_FLOAT
:
2834 case TYPESPEC_DOUBLE
:
2835 case TYPESPEC_SIGNED
:
2836 case TYPESPEC_UNSIGNED
:
2838 case TYPESPEC_COMPLEX
:
2839 case TYPESPEC_IMAGINARY
:
2840 case TYPESPEC_CONST
:
2841 case TYPESPEC_ID_TYPE
:
2842 ret
= visit_field_class_specifier(ctx
, ts_list
, decl
);
2844 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Cannot visit field class specifier: ret=%d",
2851 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
,
2852 "Unexpected field class specifier type: node-type=%d",
2853 first
->u
.field_class_specifier
.type
);
2862 ctf_field_class_destroy(*decl
);
2867 static int visit_event_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
2868 struct ctf_event_class
*event_class
, uint64_t *stream_id
,
2874 switch (node
->type
) {
2876 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
2877 &node
->u
.field_class_def
.field_class_declarators
);
2879 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in event class.");
2883 case NODE_TYPEALIAS
:
2884 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
2885 node
->u
.field_class_alias
.alias
);
2887 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2888 "Cannot add field class alias found in event class.");
2892 case NODE_CTF_EXPRESSION
:
2894 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
2896 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
2901 if (strcmp(left
, "name") == 0) {
2902 /* This is already known at this stage */
2903 if (_IS_SET(set
, _EVENT_NAME_SET
)) {
2904 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "name", "event class");
2909 _SET(set
, _EVENT_NAME_SET
);
2910 } else if (strcmp(left
, "id") == 0) {
2913 if (_IS_SET(set
, _EVENT_ID_SET
)) {
2914 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "event class");
2919 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
2920 /* Only read "id" if get_unary_unsigned() succeeded. */
2921 if (ret
|| (!ret
&& id
< 0)) {
2922 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2923 node
, "Unexpected unary expression for event class's `id` attribute.");
2928 event_class
->id
= id
;
2929 _SET(set
, _EVENT_ID_SET
);
2930 } else if (strcmp(left
, "stream_id") == 0) {
2931 if (_IS_SET(set
, _EVENT_STREAM_ID_SET
)) {
2932 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "stream_id", "event class");
2937 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, stream_id
);
2940 * Only read "stream_id" if get_unary_unsigned()
2944 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2945 node
, "Unexpected unary expression for event class's `stream_id` attribute.");
2950 _SET(set
, _EVENT_STREAM_ID_SET
);
2951 } else if (strcmp(left
, "context") == 0) {
2952 if (_IS_SET(set
, _EVENT_CONTEXT_SET
)) {
2953 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `context` entry in event class.");
2958 ret
= visit_field_class_specifier_list(
2959 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2960 &event_class
->spec_context_fc
);
2962 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2963 "Cannot create event class's context field class.");
2967 BT_ASSERT(event_class
->spec_context_fc
);
2968 _SET(set
, _EVENT_CONTEXT_SET
);
2969 } else if (strcmp(left
, "fields") == 0) {
2970 if (_IS_SET(set
, _EVENT_FIELDS_SET
)) {
2971 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `fields` entry in event class.");
2976 ret
= visit_field_class_specifier_list(
2977 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2978 &event_class
->payload_fc
);
2980 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2981 "Cannot create event class's payload field class.");
2985 BT_ASSERT(event_class
->payload_fc
);
2986 _SET(set
, _EVENT_FIELDS_SET
);
2987 } else if (strcmp(left
, "loglevel") == 0) {
2988 uint64_t loglevel_value
;
2989 bool is_log_level_known
= true;
2990 bt_event_class_log_level log_level
;
2992 if (_IS_SET(set
, _EVENT_LOG_LEVEL_SET
)) {
2993 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "loglevel", "event class");
2998 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &loglevel_value
);
3000 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3001 node
, "Unexpected unary expression for event class's `loglevel` attribute.");
3006 switch (loglevel_value
) {
3008 log_level
= BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
;
3011 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ALERT
;
3014 log_level
= BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
;
3017 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ERROR
;
3020 log_level
= BT_EVENT_CLASS_LOG_LEVEL_WARNING
;
3023 log_level
= BT_EVENT_CLASS_LOG_LEVEL_NOTICE
;
3026 log_level
= BT_EVENT_CLASS_LOG_LEVEL_INFO
;
3029 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
;
3032 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
;
3035 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
;
3038 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
;
3041 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
;
3044 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
;
3047 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
;
3050 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG
;
3053 is_log_level_known
= false;
3056 "Not setting event class's log level because its value is unknown: "
3057 "log-level=%" PRIu64
,
3061 if (is_log_level_known
) {
3062 ctf_event_class_set_log_level(event_class
, log_level
);
3065 _SET(set
, _EVENT_LOG_LEVEL_SET
);
3066 } else if (strcmp(left
, "model.emf.uri") == 0) {
3069 if (_IS_SET(set
, _EVENT_MODEL_EMF_URI_SET
)) {
3070 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "model.emf.uri", "event class");
3075 right
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.right
);
3077 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3079 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3084 if (strlen(right
) == 0) {
3085 _BT_COMP_LOGW_NODE(node
, "Not setting event class's EMF URI because it's empty.");
3087 g_string_assign(event_class
->emf_uri
, right
);
3091 _SET(set
, _EVENT_MODEL_EMF_URI_SET
);
3093 _BT_COMP_LOGW_NODE(node
,
3094 "Unknown attribute in event class: "
3117 static char *get_event_decl_name(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3121 struct ctf_node
*iter
;
3122 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3124 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3125 if (iter
->type
!= NODE_CTF_EXPRESSION
) {
3129 left
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.left
);
3131 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot concatenate unary strings.");
3135 if (strcmp(left
, "name") == 0) {
3136 name
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.right
);
3138 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3139 iter
, "Unexpected unary expression for event class's `name` attribute.");
3159 static int visit_event_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3163 struct ctf_node
*iter
;
3164 uint64_t stream_id
= 0;
3165 char *event_name
= NULL
;
3166 struct ctf_event_class
*event_class
= NULL
;
3167 struct ctf_stream_class
*stream_class
= NULL
;
3168 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3169 bool pop_scope
= false;
3171 if (node
->visited
) {
3175 node
->visited
= TRUE
;
3176 event_name
= get_event_decl_name(ctx
, node
);
3178 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `name` attribute in event class.");
3183 event_class
= ctf_event_class_create();
3184 BT_ASSERT(event_class
);
3185 g_string_assign(event_class
->name
, event_name
);
3186 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3189 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3190 ret
= visit_event_decl_entry(ctx
, iter
, event_class
, &stream_id
, &set
);
3192 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3193 "Cannot visit event class's entry: "
3200 if (!_IS_SET(&set
, _EVENT_STREAM_ID_SET
)) {
3202 * Allow missing stream_id if there is only a single
3205 switch (ctx
->ctf_tc
->stream_classes
->len
) {
3207 /* Create implicit stream class if there's none */
3209 stream_class
= ctf_stream_class_create();
3210 BT_ASSERT(stream_class
);
3211 stream_class
->id
= stream_id
;
3212 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3215 /* Single stream class: get its ID */
3216 stream_class
= (ctf_stream_class
*) ctx
->ctf_tc
->stream_classes
->pdata
[0];
3217 stream_id
= stream_class
->id
;
3220 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `stream_id` attribute in event class.");
3226 /* We have the stream ID now; get the stream class if found */
3227 if (!stream_class
) {
3228 stream_class
= ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_id
);
3229 if (!stream_class
) {
3230 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3231 "Cannot find stream class at this point: "
3239 BT_ASSERT(stream_class
);
3241 if (!_IS_SET(&set
, _EVENT_ID_SET
)) {
3242 /* Allow only one event without ID per stream */
3243 if (stream_class
->event_classes
->len
!= 0) {
3244 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `id` attribute in event class.");
3250 event_class
->id
= 0;
3253 if (ctf_stream_class_borrow_event_class_by_id(stream_class
, event_class
->id
)) {
3254 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3255 "Duplicate event class (same ID) in the same stream class: "
3262 ctf_stream_class_append_event_class(stream_class
, event_class
);
3267 ctf_event_class_destroy(event_class
);
3284 static int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3285 struct ctf_field_class
*fc
)
3287 struct ctf_clock_class
*clock_class_to_map_to
= NULL
;
3288 uint64_t clock_class_count
;
3294 if (fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&& fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3298 ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
3300 if (int_fc
->mapped_clock_class
) {
3301 /* Already mapped */
3305 clock_class_count
= ctx
->ctf_tc
->clock_classes
->len
;
3307 switch (clock_class_count
) {
3310 * No clock class exists in the trace at this point. Create an
3311 * implicit one at 1 GHz, named `default`, and use this clock
3314 clock_class_to_map_to
= ctf_clock_class_create();
3315 BT_ASSERT(clock_class_to_map_to
);
3316 clock_class_to_map_to
->frequency
= UINT64_C(1000000000);
3317 g_string_assign(clock_class_to_map_to
->name
, "default");
3318 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock_class_to_map_to
);
3322 * Only one clock class exists in the trace at this point: use
3325 clock_class_to_map_to
= (ctf_clock_class
*) ctx
->ctf_tc
->clock_classes
->pdata
[0];
3329 * Timestamp field not mapped to a clock class and there's more
3330 * than one clock class in the trace: this is an error.
3332 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3333 "Timestamp field found with no mapped clock class, "
3334 "but there's more than one clock class in the trace at this point.");
3338 BT_ASSERT(clock_class_to_map_to
);
3339 int_fc
->mapped_clock_class
= clock_class_to_map_to
;
3344 static int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3345 struct ctf_field_class
*root_fc
,
3346 const char *field_name
)
3350 struct ctf_field_class_struct
*struct_fc
= (ctf_field_class_struct
*) root_fc
;
3351 struct ctf_field_class_variant
*var_fc
= (ctf_field_class_variant
*) root_fc
;
3357 if (root_fc
->type
!= CTF_FIELD_CLASS_TYPE_STRUCT
&&
3358 root_fc
->type
!= CTF_FIELD_CLASS_TYPE_VARIANT
) {
3362 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3363 count
= struct_fc
->members
->len
;
3365 count
= var_fc
->options
->len
;
3368 for (i
= 0; i
< count
; i
++) {
3369 struct ctf_named_field_class
*named_fc
= NULL
;
3371 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3372 named_fc
= ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
3373 } else if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
3374 named_fc
= ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
3379 if (strcmp(named_fc
->name
->str
, field_name
) == 0) {
3380 ret
= auto_map_field_to_trace_clock_class(ctx
, named_fc
->fc
);
3382 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3383 "Cannot automatically map field to trace's clock class: "
3384 "field-name=\"%s\"",
3390 ret
= auto_map_fields_to_trace_clock_class(ctx
, named_fc
->fc
, field_name
);
3392 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3393 "Cannot automatically map structure or variant field class's fields to trace's clock class: "
3394 "field-name=\"%s\", root-field-name=\"%s\"",
3395 field_name
, named_fc
->name
->str
);
3404 static int visit_stream_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3405 struct ctf_stream_class
*stream_class
, int *set
)
3410 switch (node
->type
) {
3412 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3413 &node
->u
.field_class_def
.field_class_declarators
);
3415 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in stream class.");
3419 case NODE_TYPEALIAS
:
3420 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3421 node
->u
.field_class_alias
.alias
);
3423 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3424 "Cannot add field class alias found in stream class.");
3428 case NODE_CTF_EXPRESSION
:
3430 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3432 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3437 if (strcmp(left
, "id") == 0) {
3440 if (_IS_SET(set
, _STREAM_ID_SET
)) {
3441 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "stream declaration");
3446 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
3448 /* Only read "id" if get_unary_unsigned() succeeded. */
3449 if (ret
|| (!ret
&& id
< 0)) {
3450 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3451 node
, "Unexpected unary expression for stream class's `id` attribute.");
3456 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, id
)) {
3457 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3458 node
, "Duplicate stream class (same ID): id=%" PRId64
, id
);
3463 stream_class
->id
= id
;
3464 _SET(set
, _STREAM_ID_SET
);
3465 } else if (strcmp(left
, "event.header") == 0) {
3466 if (_IS_SET(set
, _STREAM_EVENT_HEADER_SET
)) {
3467 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3468 "Duplicate `event.header` entry in stream class.");
3473 ret
= visit_field_class_specifier_list(
3474 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3475 &stream_class
->event_header_fc
);
3477 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3478 node
, "Cannot create stream class's event header field class.");
3482 BT_ASSERT(stream_class
->event_header_fc
);
3483 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->event_header_fc
,
3486 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3488 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3492 _SET(set
, _STREAM_EVENT_HEADER_SET
);
3493 } else if (strcmp(left
, "event.context") == 0) {
3494 if (_IS_SET(set
, _STREAM_EVENT_CONTEXT_SET
)) {
3495 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3496 "Duplicate `event.context` entry in stream class.");
3501 ret
= visit_field_class_specifier_list(
3502 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3503 &stream_class
->event_common_context_fc
);
3505 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3506 node
, "Cannot create stream class's event context field class.");
3510 BT_ASSERT(stream_class
->event_common_context_fc
);
3511 _SET(set
, _STREAM_EVENT_CONTEXT_SET
);
3512 } else if (strcmp(left
, "packet.context") == 0) {
3513 if (_IS_SET(set
, _STREAM_PACKET_CONTEXT_SET
)) {
3514 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3515 node
, "Duplicate `packet.context` entry in stream class.");
3520 ret
= visit_field_class_specifier_list(
3521 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3522 &stream_class
->packet_context_fc
);
3524 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3525 node
, "Cannot create stream class's packet context field class.");
3529 BT_ASSERT(stream_class
->packet_context_fc
);
3530 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3533 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3535 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3539 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3542 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3544 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3548 _SET(set
, _STREAM_PACKET_CONTEXT_SET
);
3550 _BT_COMP_LOGW_NODE(node
,
3551 "Unknown attribute in stream class: "
3573 static int visit_stream_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3577 struct ctf_node
*iter
;
3578 struct ctf_stream_class
*stream_class
= NULL
;
3579 struct bt_list_head
*decl_list
= &node
->u
.stream
.declaration_list
;
3581 if (node
->visited
) {
3585 node
->visited
= TRUE
;
3586 stream_class
= ctf_stream_class_create();
3587 BT_ASSERT(stream_class
);
3588 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3590 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3591 ret
= visit_stream_decl_entry(ctx
, iter
, stream_class
, &set
);
3593 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3594 "Cannot visit stream class's entry: "
3604 if (_IS_SET(&set
, _STREAM_ID_SET
)) {
3605 /* Check that packet header has `stream_id` field */
3606 struct ctf_named_field_class
*named_fc
= NULL
;
3608 if (!ctx
->ctf_tc
->packet_header_fc
) {
3609 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Stream class has a `id` attribute, "
3610 "but trace has no packet header field class.");
3615 named_fc
= ctf_field_class_struct_borrow_member_by_name(
3616 ctf_field_class_as_struct(ctx
->ctf_tc
->packet_header_fc
), "stream_id");
3618 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3619 node
, "Stream class has a `id` attribute, "
3620 "but trace's packet header field class has no `stream_id` field.");
3625 if (named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3626 named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3627 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3629 "Stream class has a `id` attribute, "
3630 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3635 /* Allow only _one_ ID-less stream */
3636 if (ctx
->ctf_tc
->stream_classes
->len
!= 0) {
3637 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3639 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3644 /* Automatic ID: 0 */
3645 stream_class
->id
= 0;
3649 * Make sure that this stream class's ID is currently unique in
3652 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_class
->id
)) {
3653 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate stream class (same ID): id=%" PRId64
,
3659 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3660 stream_class
= NULL
;
3664 ctf_stream_class_destroy(stream_class
);
3665 stream_class
= NULL
;
3671 static int visit_trace_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3678 switch (node
->type
) {
3680 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3681 &node
->u
.field_class_def
.field_class_declarators
);
3683 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3684 node
, "Cannot add field class found in trace (`trace` block).");
3688 case NODE_TYPEALIAS
:
3689 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3690 node
->u
.field_class_alias
.alias
);
3692 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3693 node
, "Cannot add field class alias found in trace (`trace` block).");
3697 case NODE_CTF_EXPRESSION
:
3699 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3701 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3706 if (strcmp(left
, "major") == 0) {
3707 if (_IS_SET(set
, _TRACE_MAJOR_SET
)) {
3708 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "major", "trace");
3713 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3715 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3716 node
, "Unexpected unary expression for trace's `major` attribute.");
3722 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3723 "Invalid trace's `minor` attribute: expecting 1.");
3728 ctx
->ctf_tc
->major
= val
;
3729 _SET(set
, _TRACE_MAJOR_SET
);
3730 } else if (strcmp(left
, "minor") == 0) {
3731 if (_IS_SET(set
, _TRACE_MINOR_SET
)) {
3732 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "minor", "trace");
3737 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3739 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3740 node
, "Unexpected unary expression for trace's `minor` attribute.");
3746 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3747 "Invalid trace's `minor` attribute: expecting 8.");
3752 ctx
->ctf_tc
->minor
= val
;
3753 _SET(set
, _TRACE_MINOR_SET
);
3754 } else if (strcmp(left
, "uuid") == 0) {
3755 if (_IS_SET(set
, _TRACE_UUID_SET
)) {
3756 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "uuid", "trace");
3761 ret
= get_unary_uuid(ctx
, &node
->u
.ctf_expression
.right
, ctx
->ctf_tc
->uuid
);
3763 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid trace's `uuid` attribute.");
3767 ctx
->ctf_tc
->is_uuid_set
= true;
3768 _SET(set
, _TRACE_UUID_SET
);
3769 } else if (strcmp(left
, "byte_order") == 0) {
3770 /* Default byte order is already known at this stage */
3771 if (_IS_SET(set
, _TRACE_BYTE_ORDER_SET
)) {
3772 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
3777 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
!= CTF_BYTE_ORDER_UNKNOWN
);
3778 _SET(set
, _TRACE_BYTE_ORDER_SET
);
3779 } else if (strcmp(left
, "packet.header") == 0) {
3780 if (_IS_SET(set
, _TRACE_PACKET_HEADER_SET
)) {
3781 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `packet.header` entry in trace.");
3786 ret
= visit_field_class_specifier_list(
3787 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3788 &ctx
->ctf_tc
->packet_header_fc
);
3790 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3791 "Cannot create trace's packet header field class.");
3795 BT_ASSERT(ctx
->ctf_tc
->packet_header_fc
);
3796 _SET(set
, _TRACE_PACKET_HEADER_SET
);
3798 _BT_COMP_LOGW_NODE(node
,
3799 "Unknown attribute in stream class: "
3809 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unknown expression in trace.");
3821 static int visit_trace_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3825 struct ctf_node
*iter
;
3826 struct bt_list_head
*decl_list
= &node
->u
.trace
.declaration_list
;
3828 if (node
->visited
) {
3832 node
->visited
= TRUE
;
3834 if (ctx
->is_trace_visited
) {
3835 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
3840 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3842 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3843 ret
= visit_trace_decl_entry(ctx
, iter
, &set
);
3845 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3846 "Cannot visit trace's entry (`trace` block): "
3856 if (!_IS_SET(&set
, _TRACE_MAJOR_SET
)) {
3857 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3858 "Missing `major` attribute in trace (`trace` block).");
3863 if (!_IS_SET(&set
, _TRACE_MINOR_SET
)) {
3864 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3865 "Missing `minor` attribute in trace (`trace` block).");
3870 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3871 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3872 "Missing `byte_order` attribute in trace (`trace` block).");
3877 ctx
->is_trace_visited
= true;
3886 static int visit_env(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3890 struct ctf_node
*entry_node
;
3891 struct bt_list_head
*decl_list
= &node
->u
.env
.declaration_list
;
3893 if (node
->visited
) {
3897 node
->visited
= TRUE
;
3899 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
3900 struct bt_list_head
*right_head
= &entry_node
->u
.ctf_expression
.right
;
3902 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
3903 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
3904 "Wrong expression in environment entry: "
3911 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
3913 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot get environment entry's name.");
3918 if (is_unary_string(right_head
)) {
3919 char *right
= ctf_ast_concatenate_unary_strings(right_head
);
3922 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3924 "Unexpected unary expression for environment entry's value: "
3931 if (strcmp(left
, "tracer_name") == 0) {
3932 if (strncmp(right
, "lttng", 5) == 0) {
3933 BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: "
3934 "tracer-name=\"%s\"",
3936 ctx
->is_lttng
= true;
3940 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
,
3943 } else if (is_unary_unsigned(right_head
) || is_unary_signed(right_head
)) {
3946 if (is_unary_unsigned(right_head
)) {
3947 ret
= get_unary_unsigned(ctx
, right_head
, (uint64_t *) &v
);
3949 ret
= get_unary_signed(right_head
, &v
);
3952 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3954 "Unexpected unary expression for environment entry's value: "
3961 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
,
3964 _BT_COMP_LOGW_NODE(entry_node
,
3965 "Environment entry has unknown type: "
3982 static int set_trace_byte_order(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*trace_node
)
3987 struct ctf_node
*node
;
3988 struct bt_list_head
*decl_list
= &trace_node
->u
.trace
.declaration_list
;
3990 bt_list_for_each_entry (node
, decl_list
, siblings
) {
3991 if (node
->type
== NODE_CTF_EXPRESSION
) {
3992 struct ctf_node
*right_node
;
3994 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3996 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
4001 if (strcmp(left
, "byte_order") == 0) {
4002 enum ctf_byte_order bo
;
4004 if (_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4005 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
4010 _SET(&set
, _TRACE_BYTE_ORDER_SET
);
4012 _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4013 bo
= byte_order_from_unary_expr(ctx
, right_node
);
4014 if (bo
== CTF_BYTE_ORDER_UNKNOWN
) {
4015 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4016 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4017 "expecting `le`, `be`, or `network`.");
4020 } else if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
4021 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4022 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4023 "cannot be set to `native` here.");
4028 ctx
->ctf_tc
->default_byte_order
= bo
;
4036 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4037 _BT_COMP_LOGE_APPEND_CAUSE_NODE(trace_node
,
4038 "Missing `byte_order` attribute in trace (`trace` block).");
4050 static int visit_clock_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
4051 struct ctf_clock_class
*clock
, int *set
, int64_t *offset_seconds
,
4052 uint64_t *offset_cycles
)
4057 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4058 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
4064 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
4066 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot concatenate unary strings.");
4071 if (strcmp(left
, "name") == 0) {
4074 if (_IS_SET(set
, _CLOCK_NAME_SET
)) {
4075 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "name", "clock class");
4080 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4082 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4083 entry_node
, "Unexpected unary expression for clock class's `name` attribute.");
4088 g_string_assign(clock
->name
, right
);
4090 _SET(set
, _CLOCK_NAME_SET
);
4091 } else if (strcmp(left
, "uuid") == 0) {
4094 if (_IS_SET(set
, _CLOCK_UUID_SET
)) {
4095 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "uuid", "clock class");
4100 ret
= get_unary_uuid(ctx
, &entry_node
->u
.ctf_expression
.right
, uuid
);
4102 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Invalid clock class's `uuid` attribute.");
4106 clock
->has_uuid
= true;
4107 bt_uuid_copy(clock
->uuid
, uuid
);
4108 _SET(set
, _CLOCK_UUID_SET
);
4109 } else if (strcmp(left
, "description") == 0) {
4112 if (_IS_SET(set
, _CLOCK_DESCRIPTION_SET
)) {
4113 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "description", "clock class");
4118 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4120 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4122 "Unexpected unary expression for clock class's `description` attribute.");
4127 g_string_assign(clock
->description
, right
);
4129 _SET(set
, _CLOCK_DESCRIPTION_SET
);
4130 } else if (strcmp(left
, "freq") == 0) {
4131 uint64_t freq
= UINT64_C(-1);
4133 if (_IS_SET(set
, _CLOCK_FREQ_SET
)) {
4134 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "freq", "clock class");
4139 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &freq
);
4141 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4142 entry_node
, "Unexpected unary expression for clock class's `freq` attribute.");
4147 if (freq
== UINT64_C(-1) || freq
== 0) {
4148 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4149 "Invalid clock class frequency: freq=%" PRIu64
, freq
);
4154 clock
->frequency
= freq
;
4155 _SET(set
, _CLOCK_FREQ_SET
);
4156 } else if (strcmp(left
, "precision") == 0) {
4159 if (_IS_SET(set
, _CLOCK_PRECISION_SET
)) {
4160 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "precision", "clock class");
4165 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &precision
);
4167 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4168 entry_node
, "Unexpected unary expression for clock class's `precision` attribute.");
4173 clock
->precision
= precision
;
4174 _SET(set
, _CLOCK_PRECISION_SET
);
4175 } else if (strcmp(left
, "offset_s") == 0) {
4176 if (_IS_SET(set
, _CLOCK_OFFSET_S_SET
)) {
4177 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset_s", "clock class");
4182 ret
= get_unary_signed(&entry_node
->u
.ctf_expression
.right
, offset_seconds
);
4184 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4185 entry_node
, "Unexpected unary expression for clock class's `offset_s` attribute.");
4190 _SET(set
, _CLOCK_OFFSET_S_SET
);
4191 } else if (strcmp(left
, "offset") == 0) {
4192 if (_IS_SET(set
, _CLOCK_OFFSET_SET
)) {
4193 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset", "clock class");
4198 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, offset_cycles
);
4200 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4201 entry_node
, "Unexpected unary expression for clock class's `offset` attribute.");
4206 _SET(set
, _CLOCK_OFFSET_SET
);
4207 } else if (strcmp(left
, "absolute") == 0) {
4208 struct ctf_node
*right
;
4210 if (_IS_SET(set
, _CLOCK_ABSOLUTE_SET
)) {
4211 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "absolute", "clock class");
4217 _BT_LIST_FIRST_ENTRY(&entry_node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4218 ret
= get_boolean(ctx
, right
);
4220 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4221 entry_node
, "Unexpected unary expression for clock class's `absolute` attribute.");
4226 clock
->is_absolute
= ret
;
4227 _SET(set
, _CLOCK_ABSOLUTE_SET
);
4229 _BT_COMP_LOGW_NODE(entry_node
, "Unknown attribute in clock class: attr-name=\"%s\"", left
);
4241 static inline uint64_t cycles_from_ns(uint64_t frequency
, uint64_t ns
)
4246 if (frequency
== UINT64_C(1000000000)) {
4249 cycles
= (uint64_t) (((double) ns
* (double) frequency
) / 1e9
);
4255 static void calibrate_clock_class_offsets(int64_t *offset_seconds
, uint64_t *offset_cycles
,
4258 if (*offset_cycles
>= freq
) {
4259 const uint64_t s_in_offset_cycles
= *offset_cycles
/ freq
;
4261 *offset_seconds
+= (int64_t) s_in_offset_cycles
;
4262 *offset_cycles
-= (s_in_offset_cycles
* freq
);
4266 static void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir
*ctx
,
4267 struct ctf_clock_class
*clock
)
4269 if (ctx
->decoder_config
.force_clock_class_origin_unix_epoch
) {
4270 clock
->is_absolute
= true;
4276 static void apply_clock_class_offset(struct ctf_visitor_generate_ir
*ctx
,
4277 struct ctf_clock_class
*clock
)
4280 int64_t offset_s_to_apply
= ctx
->decoder_config
.clock_class_offset_s
;
4281 uint64_t offset_ns_to_apply
;
4282 int64_t cur_offset_s
;
4283 uint64_t cur_offset_cycles
;
4285 if (ctx
->decoder_config
.clock_class_offset_s
== 0 &&
4286 ctx
->decoder_config
.clock_class_offset_ns
== 0) {
4290 /* Transfer nanoseconds to seconds as much as possible */
4291 if (ctx
->decoder_config
.clock_class_offset_ns
< 0) {
4292 const int64_t abs_ns
= -ctx
->decoder_config
.clock_class_offset_ns
;
4293 const int64_t abs_extra_s
= abs_ns
/ INT64_C(1000000000) + 1;
4294 const int64_t extra_s
= -abs_extra_s
;
4295 const int64_t offset_ns
=
4296 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4298 BT_ASSERT(offset_ns
> 0);
4299 offset_ns_to_apply
= (uint64_t) offset_ns
;
4300 offset_s_to_apply
+= extra_s
;
4302 const int64_t extra_s
= ctx
->decoder_config
.clock_class_offset_ns
/ INT64_C(1000000000);
4303 const int64_t offset_ns
=
4304 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4306 BT_ASSERT(offset_ns
>= 0);
4307 offset_ns_to_apply
= (uint64_t) offset_ns
;
4308 offset_s_to_apply
+= extra_s
;
4311 freq
= clock
->frequency
;
4312 cur_offset_s
= clock
->offset_seconds
;
4313 cur_offset_cycles
= clock
->offset_cycles
;
4316 cur_offset_s
+= offset_s_to_apply
;
4317 cur_offset_cycles
+= cycles_from_ns(freq
, offset_ns_to_apply
);
4320 * Recalibrate offsets because the part in cycles can be greater
4321 * than the frequency at this point.
4323 calibrate_clock_class_offsets(&cur_offset_s
, &cur_offset_cycles
, freq
);
4325 /* Set final offsets */
4326 clock
->offset_seconds
= cur_offset_s
;
4327 clock
->offset_cycles
= cur_offset_cycles
;
4333 static int visit_clock_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*clock_node
)
4337 struct ctf_clock_class
*clock
;
4338 struct ctf_node
*entry_node
;
4339 struct bt_list_head
*decl_list
= &clock_node
->u
.clock
.declaration_list
;
4340 const char *clock_class_name
;
4341 int64_t offset_seconds
= 0;
4342 uint64_t offset_cycles
= 0;
4345 if (clock_node
->visited
) {
4349 clock_node
->visited
= TRUE
;
4351 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4352 clock
= ctf_clock_class_create();
4354 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
, "Cannot create default clock class.");
4359 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
4360 ret
= visit_clock_decl_entry(ctx
, entry_node
, clock
, &set
, &offset_seconds
, &offset_cycles
);
4362 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot visit clock class's entry: ret=%d",
4368 if (!_IS_SET(&set
, _CLOCK_NAME_SET
)) {
4369 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
, "Missing `name` attribute in clock class.");
4374 clock_class_name
= clock
->name
->str
;
4375 BT_ASSERT(clock_class_name
);
4376 if (ctx
->is_lttng
&& strcmp(clock_class_name
, "monotonic") == 0) {
4378 * Old versions of LTTng forgot to set its clock class
4379 * as absolute, even if it is. This is important because
4380 * it's a condition to be able to sort messages
4381 * from different sources.
4383 clock
->is_absolute
= true;
4387 * Adjust offsets so that the part in cycles is less than the
4388 * frequency (move to the part in seconds).
4390 freq
= clock
->frequency
;
4391 calibrate_clock_class_offsets(&offset_seconds
, &offset_cycles
, freq
);
4392 BT_ASSERT(offset_cycles
< clock
->frequency
);
4393 clock
->offset_seconds
= offset_seconds
;
4394 clock
->offset_cycles
= offset_cycles
;
4395 apply_clock_class_offset(ctx
, clock
);
4396 apply_clock_class_is_absolute(ctx
, clock
);
4397 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock
);
4402 ctf_clock_class_destroy(clock
);
4408 static int visit_root_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*root_decl_node
)
4412 if (root_decl_node
->visited
) {
4416 root_decl_node
->visited
= TRUE
;
4418 switch (root_decl_node
->type
) {
4421 visit_field_class_def(ctx
, root_decl_node
->u
.field_class_def
.field_class_specifier_list
,
4422 &root_decl_node
->u
.field_class_def
.field_class_declarators
);
4424 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4425 "Cannot add field class found in root scope.");
4429 case NODE_TYPEALIAS
:
4430 ret
= visit_field_class_alias(ctx
, root_decl_node
->u
.field_class_alias
.target
,
4431 root_decl_node
->u
.field_class_alias
.alias
);
4433 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4434 "Cannot add field class alias found in root scope.");
4438 case NODE_TYPE_SPECIFIER_LIST
:
4440 struct ctf_field_class
*decl
= NULL
;
4443 * Just add the field class specifier to the root
4444 * declaration scope. Put local reference.
4446 ret
= visit_field_class_specifier_list(ctx
, root_decl_node
, &decl
);
4448 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4449 "Cannot visit root scope's field class: "
4456 ctf_field_class_destroy(decl
);
4461 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
, "Unexpected node type: node-type=%d",
4462 root_decl_node
->type
);
4471 struct ctf_visitor_generate_ir
*
4472 ctf_visitor_generate_ir_create(const struct ctf_metadata_decoder_config
*decoder_config
)
4474 struct ctf_visitor_generate_ir
*ctx
= NULL
;
4476 /* Create visitor's context */
4477 ctx
= ctx_create(decoder_config
);
4479 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
, decoder_config
->self_comp
,
4480 "Cannot create visitor's context.");
4494 void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir
*visitor
)
4496 ctx_destroy(visitor
);
4499 bt_trace_class
*ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4503 if (ctx
->trace_class
) {
4504 bt_trace_class_get_ref(ctx
->trace_class
);
4507 return ctx
->trace_class
;
4510 struct ctf_trace_class
*
4511 ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4514 BT_ASSERT_DBG(ctx
->ctf_tc
);
4518 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
4522 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
4524 switch (node
->type
) {
4527 struct ctf_node
*iter
;
4528 bool got_trace_decl
= false;
4531 * The first thing we need is the native byte order of
4532 * the trace block, because early class aliases can have
4533 * a `byte_order` attribute set to `native`. If we don't
4534 * have the native byte order yet, and we don't have any
4535 * trace block yet, then fail with EINCOMPLETE.
4537 if (ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
4538 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4539 if (got_trace_decl
) {
4540 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
4545 ret
= set_trace_byte_order(ctx
, iter
);
4547 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4548 "Cannot set trace's native byte order: "
4554 got_trace_decl
= true;
4557 if (!got_trace_decl
) {
4558 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
4564 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_LITTLE
||
4565 ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_BIG
);
4566 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4569 bt_list_for_each_entry (iter
, &node
->u
.root
.env
, siblings
) {
4570 ret
= visit_env(ctx
, iter
);
4572 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4574 "Cannot visit trace's environment (`env` block) entry: "
4581 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4584 * Visit clock blocks.
4586 bt_list_for_each_entry (iter
, &node
->u
.root
.clock
, siblings
) {
4587 ret
= visit_clock_decl(ctx
, iter
);
4589 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit clock class: ret=%d", ret
);
4594 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4597 * Visit root declarations next, as they can be used by any
4600 bt_list_for_each_entry (iter
, &node
->u
.root
.declaration_list
, siblings
) {
4601 ret
= visit_root_decl(ctx
, iter
);
4603 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit root entry: ret=%d", ret
);
4608 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4610 /* Callsite blocks are not supported */
4611 bt_list_for_each_entry (iter
, &node
->u
.root
.callsite
, siblings
) {
4612 _BT_COMP_LOGW_NODE(iter
, "\"callsite\" blocks are not supported as of this version.");
4615 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4618 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4619 ret
= visit_trace_decl(ctx
, iter
);
4621 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4622 "Cannot visit trace (`trace` block): "
4629 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4632 bt_list_for_each_entry (iter
, &node
->u
.root
.stream
, siblings
) {
4633 ret
= visit_stream_decl(ctx
, iter
);
4635 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit stream class: ret=%d", ret
);
4640 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4643 bt_list_for_each_entry (iter
, &node
->u
.root
.event
, siblings
) {
4644 ret
= visit_event_decl(ctx
, iter
);
4646 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit event class: ret=%d", ret
);
4651 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4655 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected node type: node-type=%d", node
->type
);
4660 /* Update default clock classes */
4661 ret
= ctf_trace_class_update_default_clock_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4667 /* Update trace class meanings */
4668 ret
= ctf_trace_class_update_meanings(ctx
->ctf_tc
);
4674 /* Update stream class configuration */
4675 ret
= ctf_trace_class_update_stream_class_config(ctx
->ctf_tc
);
4681 /* Update text arrays and sequences */
4682 ret
= ctf_trace_class_update_text_array_sequence(ctx
->ctf_tc
);
4688 /* Update structure/array/sequence alignments */
4689 ret
= ctf_trace_class_update_alignments(ctx
->ctf_tc
);
4695 /* Resolve sequence lengths and variant tags */
4696 ret
= ctf_trace_class_resolve_field_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4702 if (ctx
->trace_class
) {
4704 * Update "in IR" for field classes.
4706 * If we have no IR trace class, then we'll have no way
4707 * to create IR fields anyway, so we leave all the
4708 * `in_ir` members false.
4710 ret
= ctf_trace_class_update_in_ir(ctx
->ctf_tc
);
4717 /* Update saved value indexes */
4718 ret
= ctf_trace_class_update_value_storing_indexes(ctx
->ctf_tc
);
4724 /* Validate what we have so far */
4725 ret
= ctf_trace_class_validate(ctx
->ctf_tc
, &ctx
->log_cfg
);
4732 * If there are fields which are not related to the CTF format
4733 * itself in the packet header and in event header field
4734 * classes, warn about it because they are never translated.
4736 ctf_trace_class_warn_meaningless_header_fields(ctx
->ctf_tc
, &ctx
->log_cfg
);
4738 if (ctx
->trace_class
) {
4739 /* Copy new CTF metadata -> new IR metadata */
4740 ret
= ctf_trace_class_translate(ctx
->log_cfg
.self_comp
, ctx
->trace_class
, ctx
->ctf_tc
);