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).
18 #include <babeltrace2/babeltrace.h>
20 #define BT_COMP_LOG_SELF_COMP (ctx->log_cfg.self_comp)
21 #define BT_COMP_LOG_SELF_COMP_CLASS (ctx->log_cfg.self_comp_class)
22 #define BT_LOG_OUTPUT_LEVEL (ctx->log_cfg.log_level)
23 #define BT_LOG_TAG "PLUGIN/CTF/META/IR-VISITOR"
24 #include "logging.hpp"
25 #include "logging/comp-logging.h"
27 #include "common/assert.h"
28 #include "common/common.h"
29 #include "common/uuid.h"
30 #include "compat/endian.h" /* IWYU pragma: keep */
33 #include "ctf-meta-visitors.hpp"
34 #include "ctf-meta.hpp"
35 #include "decoder.hpp"
37 /* Bit value (left shift) */
38 #define _BV(_val) (1 << (_val))
40 /* Bit is set in a set of bits */
41 #define _IS_SET(_set, _mask) (*(_set) & (_mask))
43 /* Set bit in a set of bits */
44 #define _SET(_set, _mask) (*(_set) |= (_mask))
46 /* Try to push scope, or go to the `error` label */
47 #define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
49 ret = ctx_push_scope(ctx); \
51 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot push scope."); \
56 /* Bits for verifying existing attributes in various declarations */
59 _CLOCK_NAME_SET
= _BV(0),
60 _CLOCK_UUID_SET
= _BV(1),
61 _CLOCK_FREQ_SET
= _BV(2),
62 _CLOCK_PRECISION_SET
= _BV(3),
63 _CLOCK_OFFSET_S_SET
= _BV(4),
64 _CLOCK_OFFSET_SET
= _BV(5),
65 _CLOCK_ABSOLUTE_SET
= _BV(6),
66 _CLOCK_DESCRIPTION_SET
= _BV(7),
71 _INTEGER_ALIGN_SET
= _BV(0),
72 _INTEGER_SIZE_SET
= _BV(1),
73 _INTEGER_BASE_SET
= _BV(2),
74 _INTEGER_ENCODING_SET
= _BV(3),
75 _INTEGER_BYTE_ORDER_SET
= _BV(4),
76 _INTEGER_SIGNED_SET
= _BV(5),
77 _INTEGER_MAP_SET
= _BV(6),
82 _FLOAT_ALIGN_SET
= _BV(0),
83 _FLOAT_MANT_DIG_SET
= _BV(1),
84 _FLOAT_EXP_DIG_SET
= _BV(2),
85 _FLOAT_BYTE_ORDER_SET
= _BV(3),
90 _STRING_ENCODING_SET
= _BV(0),
95 _TRACE_MINOR_SET
= _BV(0),
96 _TRACE_MAJOR_SET
= _BV(1),
97 _TRACE_BYTE_ORDER_SET
= _BV(2),
98 _TRACE_UUID_SET
= _BV(3),
99 _TRACE_PACKET_HEADER_SET
= _BV(4),
104 _STREAM_ID_SET
= _BV(0),
105 _STREAM_PACKET_CONTEXT_SET
= _BV(1),
106 _STREAM_EVENT_HEADER_SET
= _BV(2),
107 _STREAM_EVENT_CONTEXT_SET
= _BV(3),
112 _EVENT_NAME_SET
= _BV(0),
113 _EVENT_ID_SET
= _BV(1),
114 _EVENT_MODEL_EMF_URI_SET
= _BV(2),
115 _EVENT_STREAM_ID_SET
= _BV(3),
116 _EVENT_LOG_LEVEL_SET
= _BV(4),
117 _EVENT_CONTEXT_SET
= _BV(5),
118 _EVENT_FIELDS_SET
= _BV(6),
127 LOG_LEVEL_WARNING
= 4,
128 LOG_LEVEL_NOTICE
= 5,
130 LOG_LEVEL_DEBUG_SYSTEM
= 7,
131 LOG_LEVEL_DEBUG_PROGRAM
= 8,
132 LOG_LEVEL_DEBUG_PROCESS
= 9,
133 LOG_LEVEL_DEBUG_MODULE
= 10,
134 LOG_LEVEL_DEBUG_UNIT
= 11,
135 LOG_LEVEL_DEBUG_FUNCTION
= 12,
136 LOG_LEVEL_DEBUG_LINE
= 13,
137 LOG_LEVEL_DEBUG
= 14,
141 /* Prefixes of class aliases */
142 #define _PREFIX_ALIAS 'a'
143 #define _PREFIX_ENUM 'e'
144 #define _PREFIX_STRUCT 's'
145 #define _PREFIX_VARIANT 'v'
147 /* First entry in a BT list */
148 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) bt_list_entry((_ptr)->next, _class, _member)
150 #define _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \
151 _BT_COMP_LOGE_APPEND_CAUSE_LINENO( \
152 (_node)->lineno, "Duplicate attribute in %s: attr-name=\"%s\"", _entity, _attr)
154 #define _BT_COMP_LOGE_NODE(_node, _msg, args...) _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ##args)
156 #define _BT_COMP_LOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
157 _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, _msg, ##args)
159 #define _BT_COMP_LOGW_NODE(_node, _msg, args...) _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ##args)
161 #define _BT_COMP_LOGT_NODE(_node, _msg, args...) _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ##args)
164 * Declaration scope of a visitor context. This represents a TSDL
165 * lexical scope, so that aliases and named structures, variants,
166 * and enumerations may be registered and looked up hierarchically.
168 struct ctx_decl_scope
171 * Alias name to field class.
173 * GQuark -> struct ctf_field_class * (owned by this)
175 GHashTable
*decl_map
;
177 /* Parent scope; NULL if this is the root declaration scope */
178 struct ctx_decl_scope
*parent_scope
;
182 * Visitor context (private).
184 struct ctf_visitor_generate_ir
186 struct meta_log_config log_cfg
;
188 /* Trace IR trace class being filled (owned by this) */
189 bt_trace_class
*trace_class
;
191 /* CTF meta trace being filled (owned by this) */
192 struct ctf_trace_class
*ctf_tc
;
194 /* Current declaration scope (top of the stack) (owned by this) */
195 struct ctx_decl_scope
*current_scope
;
197 /* True if trace declaration is visited */
198 bool is_trace_visited
;
200 /* True if this is an LTTng trace */
203 /* Config passed by the user */
204 struct ctf_metadata_decoder_config decoder_config
;
210 struct ctf_visitor_generate_ir
;
213 * Creates a new declaration scope.
215 * @param par_scope Parent scope (NULL if creating a root scope)
216 * @returns New declaration scope, or NULL on error
218 static struct ctx_decl_scope
*ctx_decl_scope_create(struct ctf_visitor_generate_ir
*ctx
,
219 struct ctx_decl_scope
*par_scope
)
221 struct ctx_decl_scope
*scope
;
223 scope
= g_new(struct ctx_decl_scope
, 1);
225 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate one declaration scope.");
229 scope
->decl_map
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
,
230 (GDestroyNotify
) ctf_field_class_destroy
);
231 scope
->parent_scope
= par_scope
;
238 * Destroys a declaration scope.
240 * This function does not destroy the parent scope.
242 * @param scope Scope to destroy
244 static void ctx_decl_scope_destroy(struct ctx_decl_scope
*scope
)
250 g_hash_table_destroy(scope
->decl_map
);
258 * Returns the GQuark of a prefixed alias.
260 * @param prefix Prefix character
262 * @returns Associated GQuark, or 0 on error
264 static GQuark
get_prefixed_named_quark(char prefix
, const char *name
)
267 std::string prname
= std::string
{prefix
} + name
;
268 return g_quark_from_string(prname
.c_str());
272 * Looks up a prefixed class alias within a declaration scope.
274 * @param scope Declaration scope
275 * @param prefix Prefix character
276 * @param name Alias name
277 * @param levels Number of levels to dig into (-1 means infinite)
278 * @param copy True to return a copy
279 * @returns Declaration (owned by caller if \p copy is true),
280 * or NULL if not found
282 static struct ctf_field_class
*ctx_decl_scope_lookup_prefix_alias(struct ctx_decl_scope
*scope
,
283 char prefix
, const char *name
,
284 int levels
, bool copy
)
288 struct ctf_field_class
*decl
= NULL
;
289 struct ctx_decl_scope
*cur_scope
= scope
;
293 qname
= get_prefixed_named_quark(prefix
, name
);
302 while (cur_scope
&& cur_levels
< levels
) {
303 decl
= (ctf_field_class
*) g_hash_table_lookup(cur_scope
->decl_map
,
304 (gconstpointer
) GUINT_TO_POINTER(qname
));
306 /* Caller's reference */
308 decl
= ctf_field_class_copy(decl
);
315 cur_scope
= cur_scope
->parent_scope
;
324 * Looks up a class alias within a declaration scope.
326 * @param scope Declaration scope
327 * @param name Alias name
328 * @param levels Number of levels to dig into (-1 means infinite)
329 * @param copy True to return a copy
330 * @returns Declaration (owned by caller if \p copy is true),
331 * or NULL if not found
333 static struct ctf_field_class
*ctx_decl_scope_lookup_alias(struct ctx_decl_scope
*scope
,
334 const char *name
, int levels
, bool copy
)
336 return ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ALIAS
, name
, levels
, copy
);
340 * Looks up an enumeration within a declaration scope.
342 * @param scope Declaration scope
343 * @param name Enumeration name
344 * @param levels Number of levels to dig into (-1 means infinite)
345 * @param copy True to return a copy
346 * @returns Declaration (owned by caller if \p copy is true),
347 * or NULL if not found
349 static struct ctf_field_class_enum
*
350 ctx_decl_scope_lookup_enum(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
352 return ctf_field_class_as_enum(
353 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ENUM
, name
, levels
, copy
));
357 * Looks up a structure within a declaration scope.
359 * @param scope Declaration scope
360 * @param name Structure name
361 * @param levels Number of levels to dig into (-1 means infinite)
362 * @param copy True to return a copy
363 * @returns Declaration (owned by caller if \p copy is true),
364 * or NULL if not found
366 static struct ctf_field_class_struct
*
367 ctx_decl_scope_lookup_struct(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
369 return ctf_field_class_as_struct(
370 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_STRUCT
, name
, levels
, copy
));
374 * Looks up a variant within a declaration scope.
376 * @param scope Declaration scope
377 * @param name Variant name
378 * @param levels Number of levels to dig into (-1 means infinite)
379 * @param copy True to return a copy
380 * @returns Declaration (owned by caller if \p copy is true),
381 * or NULL if not found
383 static struct ctf_field_class_variant
*
384 ctx_decl_scope_lookup_variant(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
386 return ctf_field_class_as_variant(
387 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_VARIANT
, name
, levels
, copy
));
391 * Registers a prefixed class alias within a declaration scope.
393 * @param scope Declaration scope
394 * @param prefix Prefix character
395 * @param name Alias name (non-NULL)
396 * @param decl Field class to register (copied)
397 * @returns 0 if registration went okay, negative value otherwise
399 static int ctx_decl_scope_register_prefix_alias(struct ctx_decl_scope
*scope
, char prefix
,
400 const char *name
, struct ctf_field_class
*decl
)
408 qname
= get_prefixed_named_quark(prefix
, name
);
414 /* Make sure alias does not exist in local scope */
415 if (ctx_decl_scope_lookup_prefix_alias(scope
, prefix
, name
, 1, false)) {
420 decl
= ctf_field_class_copy(decl
);
422 g_hash_table_insert(scope
->decl_map
, GUINT_TO_POINTER(qname
), decl
);
429 * Registers a class alias within a declaration scope.
431 * @param scope Declaration scope
432 * @param name Alias name (non-NULL)
433 * @param decl Field class to register (copied)
434 * @returns 0 if registration went okay, negative value otherwise
436 static int ctx_decl_scope_register_alias(struct ctx_decl_scope
*scope
, const char *name
,
437 struct ctf_field_class
*decl
)
439 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ALIAS
, name
, decl
);
443 * Registers an enumeration declaration within a declaration scope.
445 * @param scope Declaration scope
446 * @param name Enumeration name (non-NULL)
447 * @param decl Enumeration field class to register (copied)
448 * @returns 0 if registration went okay, negative value otherwise
450 static int ctx_decl_scope_register_enum(struct ctx_decl_scope
*scope
, const char *name
,
451 struct ctf_field_class_enum
*decl
)
453 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ENUM
, name
, &decl
->base
.base
.base
);
457 * Registers a structure declaration within a declaration scope.
459 * @param scope Declaration scope
460 * @param name Structure name (non-NULL)
461 * @param decl Structure field class to register (copied)
462 * @returns 0 if registration went okay, negative value otherwise
464 static int ctx_decl_scope_register_struct(struct ctx_decl_scope
*scope
, const char *name
,
465 struct ctf_field_class_struct
*decl
)
467 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_STRUCT
, name
, &decl
->base
);
471 * Registers a variant declaration within a declaration scope.
473 * @param scope Declaration scope
474 * @param name Variant name (non-NULL)
475 * @param decl Variant field class to register
476 * @returns 0 if registration went okay, negative value otherwise
478 static int ctx_decl_scope_register_variant(struct ctx_decl_scope
*scope
, const char *name
,
479 struct ctf_field_class_variant
*decl
)
481 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_VARIANT
, name
, &decl
->base
);
485 * Destroys a visitor context.
487 * @param ctx Visitor context to destroy
489 static void ctx_destroy(struct ctf_visitor_generate_ir
*ctx
)
491 struct ctx_decl_scope
*scope
;
497 scope
= ctx
->current_scope
;
500 * Destroy all scopes, from current one to the root scope.
503 struct ctx_decl_scope
*parent_scope
= scope
->parent_scope
;
505 ctx_decl_scope_destroy(scope
);
506 scope
= parent_scope
;
509 bt_trace_class_put_ref(ctx
->trace_class
);
512 ctf_trace_class_destroy(ctx
->ctf_tc
);
522 * Creates a new visitor context.
524 * @param trace Associated trace
525 * @returns New visitor context, or NULL on error
527 static struct ctf_visitor_generate_ir
*
528 ctx_create(const struct ctf_metadata_decoder_config
*decoder_config
)
530 struct ctf_visitor_generate_ir
*ctx
= NULL
;
532 BT_ASSERT(decoder_config
);
534 ctx
= g_new0(struct ctf_visitor_generate_ir
, 1);
536 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
, decoder_config
->self_comp
,
537 "Failed to allocate one visitor context.");
541 ctx
->log_cfg
.log_level
= decoder_config
->log_level
;
542 ctx
->log_cfg
.self_comp
= decoder_config
->self_comp
;
543 ctx
->log_cfg
.self_comp_class
= decoder_config
->self_comp_class
;
545 if (decoder_config
->self_comp
) {
546 ctx
->trace_class
= bt_trace_class_create(decoder_config
->self_comp
);
547 if (!ctx
->trace_class
) {
548 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create empty trace class.");
553 ctx
->ctf_tc
= ctf_trace_class_create();
555 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create CTF trace class.");
559 /* Root declaration scope */
560 ctx
->current_scope
= ctx_decl_scope_create(ctx
, NULL
);
561 if (!ctx
->current_scope
) {
562 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
566 ctx
->decoder_config
= *decoder_config
;
578 * Pushes a new declaration scope on top of a visitor context's
579 * declaration scope stack.
581 * @param ctx Visitor context
582 * @returns 0 on success, or a negative value on error
584 static int ctx_push_scope(struct ctf_visitor_generate_ir
*ctx
)
587 struct ctx_decl_scope
*new_scope
;
590 new_scope
= ctx_decl_scope_create(ctx
, ctx
->current_scope
);
592 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
597 ctx
->current_scope
= new_scope
;
603 static void ctx_pop_scope(struct ctf_visitor_generate_ir
*ctx
)
605 struct ctx_decl_scope
*parent_scope
= NULL
;
609 if (!ctx
->current_scope
) {
613 parent_scope
= ctx
->current_scope
->parent_scope
;
614 ctx_decl_scope_destroy(ctx
->current_scope
);
615 ctx
->current_scope
= parent_scope
;
621 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
622 struct ctf_node
*ts_list
,
623 struct ctf_field_class
**decl
);
625 static int is_unary_string(struct bt_list_head
*head
)
628 struct ctf_node
*node
;
630 bt_list_for_each_entry (node
, head
, siblings
) {
631 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
635 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
643 static const char *get_map_clock_name_value(struct bt_list_head
*head
)
646 struct ctf_node
*node
;
647 const char *name
= NULL
;
649 bt_list_for_each_entry (node
, head
, siblings
) {
651 int uexpr_type
= node
->u
.unary_expression
.type
;
652 int uexpr_link
= node
->u
.unary_expression
.link
;
653 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_STRING
||
654 !((uexpr_link
!= UNARY_LINK_UNKNOWN
) ^ (i
== 0));
659 /* Needs to be chained with . */
660 switch (node
->u
.unary_expression
.link
) {
663 case UNARY_ARROWLINK
:
664 case UNARY_DOTDOTDOT
:
670 src_string
= node
->u
.unary_expression
.u
.string
;
674 if (strcmp("clock", src_string
)) {
682 if (strcmp("value", src_string
)) {
687 /* Extra identifier, unknown */
700 static int is_unary_unsigned(struct bt_list_head
*head
)
703 struct ctf_node
*node
;
705 bt_list_for_each_entry (node
, head
, siblings
) {
706 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
710 if (node
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
718 static int get_unary_unsigned(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
723 struct ctf_node
*node
;
727 if (bt_list_empty(head
)) {
732 bt_list_for_each_entry (node
, head
, siblings
) {
733 int uexpr_type
= node
->u
.unary_expression
.type
;
734 int uexpr_link
= node
->u
.unary_expression
.link
;
735 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_UNSIGNED_CONSTANT
||
736 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
738 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid constant unsigned integer.");
743 *value
= node
->u
.unary_expression
.u
.unsigned_constant
;
751 static int is_unary_signed(struct bt_list_head
*head
)
754 struct ctf_node
*node
;
756 bt_list_for_each_entry (node
, head
, siblings
) {
757 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
761 if (node
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
) {
769 static int get_unary_signed(struct bt_list_head
*head
, int64_t *value
)
773 struct ctf_node
*node
;
775 bt_list_for_each_entry (node
, head
, siblings
) {
776 int uexpr_type
= node
->u
.unary_expression
.type
;
777 int uexpr_link
= node
->u
.unary_expression
.link
;
778 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
779 (uexpr_type
!= UNARY_UNSIGNED_CONSTANT
&& uexpr_type
!= UNARY_SIGNED_CONSTANT
) ||
780 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
786 switch (uexpr_type
) {
787 case UNARY_UNSIGNED_CONSTANT
:
788 *value
= (int64_t) node
->u
.unary_expression
.u
.unsigned_constant
;
790 case UNARY_SIGNED_CONSTANT
:
791 *value
= node
->u
.unary_expression
.u
.signed_constant
;
805 static int get_unary_uuid(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
808 return ctf_ast_get_unary_uuid(head
, uuid
, ctx
->log_cfg
.log_level
, ctx
->log_cfg
.self_comp
);
811 static int get_boolean(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*unary_expr
)
815 if (unary_expr
->type
!= NODE_UNARY_EXPRESSION
) {
816 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
, "Expecting unary expression: node-type=%d",
822 switch (unary_expr
->u
.unary_expression
.type
) {
823 case UNARY_UNSIGNED_CONSTANT
:
824 ret
= (unary_expr
->u
.unary_expression
.u
.unsigned_constant
!= 0);
826 case UNARY_SIGNED_CONSTANT
:
827 ret
= (unary_expr
->u
.unary_expression
.u
.signed_constant
!= 0);
831 const char *str
= unary_expr
->u
.unary_expression
.u
.string
;
833 if (strcmp(str
, "true") == 0 || strcmp(str
, "TRUE") == 0) {
835 } else if (strcmp(str
, "false") == 0 || strcmp(str
, "FALSE") == 0) {
838 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
, "Unexpected boolean value: value=\"%s\"",
846 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
847 "Unexpected unary expression type: node-type=%d",
848 unary_expr
->u
.unary_expression
.type
);
857 static enum ctf_byte_order
byte_order_from_unary_expr(struct ctf_visitor_generate_ir
*ctx
,
858 struct ctf_node
*unary_expr
)
861 enum ctf_byte_order bo
= CTF_BYTE_ORDER_UNKNOWN
;
863 if (unary_expr
->u
.unary_expression
.type
!= UNARY_STRING
) {
864 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
865 unary_expr
, "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
869 str
= unary_expr
->u
.unary_expression
.u
.string
;
871 if (strcmp(str
, "be") == 0 || strcmp(str
, "network") == 0) {
872 bo
= CTF_BYTE_ORDER_BIG
;
873 } else if (strcmp(str
, "le") == 0) {
874 bo
= CTF_BYTE_ORDER_LITTLE
;
875 } else if (strcmp(str
, "native") == 0) {
876 bo
= CTF_BYTE_ORDER_DEFAULT
;
878 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
880 "Unexpected \"byte_order\" attribute value: "
881 "expecting `be`, `le`, `network`, or `native`: value=\"%s\"",
890 static enum ctf_byte_order
get_real_byte_order(struct ctf_visitor_generate_ir
*ctx
,
891 struct ctf_node
*uexpr
)
893 enum ctf_byte_order bo
= byte_order_from_unary_expr(ctx
, uexpr
);
895 if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
896 bo
= ctx
->ctf_tc
->default_byte_order
;
902 static int is_align_valid(uint64_t align
)
904 return (align
!= 0) && !(align
& (align
- UINT64_C(1)));
907 static int get_class_specifier_name(struct ctf_visitor_generate_ir
*ctx
,
908 struct ctf_node
*cls_specifier
, GString
*str
)
912 if (cls_specifier
->type
!= NODE_TYPE_SPECIFIER
) {
913 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
, "Unexpected node type: node-type=%d",
914 cls_specifier
->type
);
919 switch (cls_specifier
->u
.field_class_specifier
.type
) {
921 g_string_append(str
, "void");
924 g_string_append(str
, "char");
927 g_string_append(str
, "short");
930 g_string_append(str
, "int");
933 g_string_append(str
, "long");
936 g_string_append(str
, "float");
938 case TYPESPEC_DOUBLE
:
939 g_string_append(str
, "double");
941 case TYPESPEC_SIGNED
:
942 g_string_append(str
, "signed");
944 case TYPESPEC_UNSIGNED
:
945 g_string_append(str
, "unsigned");
948 g_string_append(str
, "bool");
950 case TYPESPEC_COMPLEX
:
951 g_string_append(str
, "_Complex");
953 case TYPESPEC_IMAGINARY
:
954 g_string_append(str
, "_Imaginary");
957 g_string_append(str
, "const");
959 case TYPESPEC_ID_TYPE
:
960 if (cls_specifier
->u
.field_class_specifier
.id_type
) {
961 g_string_append(str
, cls_specifier
->u
.field_class_specifier
.id_type
);
964 case TYPESPEC_STRUCT
:
966 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
968 if (!node
->u
._struct
.name
) {
969 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty structure field class name.");
974 g_string_append(str
, "struct ");
975 g_string_append(str
, node
->u
._struct
.name
);
978 case TYPESPEC_VARIANT
:
980 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
982 if (!node
->u
.variant
.name
) {
983 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty variant field class name.");
988 g_string_append(str
, "variant ");
989 g_string_append(str
, node
->u
.variant
.name
);
994 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
996 if (!node
->u
._enum
.enum_id
) {
997 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
998 node
, "Unexpected empty enumeration field class (`enum`) name.");
1003 g_string_append(str
, "enum ");
1004 g_string_append(str
, node
->u
._enum
.enum_id
);
1007 case TYPESPEC_FLOATING_POINT
:
1008 case TYPESPEC_INTEGER
:
1009 case TYPESPEC_STRING
:
1011 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
->u
.field_class_specifier
.node
,
1012 "Unexpected field class specifier type: %d",
1013 cls_specifier
->u
.field_class_specifier
.type
);
1022 static int get_class_specifier_list_name(struct ctf_visitor_generate_ir
*ctx
,
1023 struct ctf_node
*cls_specifier_list
, GString
*str
)
1026 struct ctf_node
*iter
;
1027 int alias_item_nr
= 0;
1028 struct bt_list_head
*head
= &cls_specifier_list
->u
.field_class_specifier_list
.head
;
1030 bt_list_for_each_entry (iter
, head
, siblings
) {
1031 if (alias_item_nr
!= 0) {
1032 g_string_append(str
, " ");
1036 ret
= get_class_specifier_name(ctx
, iter
, str
);
1046 static GQuark
create_class_alias_identifier(struct ctf_visitor_generate_ir
*ctx
,
1047 struct ctf_node
*cls_specifier_list
,
1048 struct ctf_node
*node_field_class_declarator
)
1054 struct ctf_node
*iter
;
1055 struct bt_list_head
*pointers
= &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1057 str
= g_string_new("");
1058 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
1060 g_string_free(str
, TRUE
);
1064 bt_list_for_each_entry (iter
, pointers
, siblings
) {
1065 g_string_append(str
, " *");
1067 if (iter
->u
.pointer
.const_qualifier
) {
1068 g_string_append(str
, " const");
1072 str_c
= g_string_free(str
, FALSE
);
1073 qalias
= g_quark_from_string(str_c
);
1080 static int visit_field_class_declarator(struct ctf_visitor_generate_ir
*ctx
,
1081 struct ctf_node
*cls_specifier_list
, GQuark
*field_name
,
1082 struct ctf_node
*node_field_class_declarator
,
1083 struct ctf_field_class
**field_decl
,
1084 struct ctf_field_class
*nested_decl
)
1087 * During this whole function, nested_decl is always OURS,
1088 * whereas field_decl is an output which we create, but
1089 * belongs to the caller (it is moved).
1094 /* Validate field class declarator node */
1095 if (node_field_class_declarator
) {
1096 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_UNKNOWN
) {
1097 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1098 node_field_class_declarator
, "Unexpected field class declarator type: type=%d",
1099 node_field_class_declarator
->u
.field_class_declarator
.type
);
1104 /* TODO: GCC bitfields not supported yet */
1105 if (node_field_class_declarator
->u
.field_class_declarator
.bitfield_len
!= NULL
) {
1106 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1107 "GCC bitfields are not supported as of this version.");
1113 /* Find the right nested declaration if not provided */
1115 if (node_field_class_declarator
&&
1116 !bt_list_empty(&node_field_class_declarator
->u
.field_class_declarator
.pointers
)) {
1120 * If we have a pointer declarator, it HAS to
1121 * be present in the field class aliases (else
1125 create_class_alias_identifier(ctx
, cls_specifier_list
, node_field_class_declarator
);
1126 nested_decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, g_quark_to_string(qalias
),
1129 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1130 "Cannot find class alias: name=\"%s\"",
1131 g_quark_to_string(qalias
));
1136 if (nested_decl
->type
== CTF_FIELD_CLASS_TYPE_INT
) {
1137 /* Pointer: force integer's base to 16 */
1138 struct ctf_field_class_int
*int_fc
= ctf_field_class_as_int(nested_decl
);
1140 int_fc
->disp_base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
1143 ret
= visit_field_class_specifier_list(ctx
, cls_specifier_list
, &nested_decl
);
1145 BT_ASSERT(!nested_decl
);
1151 BT_ASSERT(nested_decl
);
1153 if (!node_field_class_declarator
) {
1154 *field_decl
= nested_decl
;
1159 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_ID
) {
1160 if (node_field_class_declarator
->u
.field_class_declarator
.u
.id
) {
1161 const char *id
= node_field_class_declarator
->u
.field_class_declarator
.u
.id
;
1163 *field_name
= g_quark_from_string(id
);
1168 *field_decl
= nested_decl
;
1172 struct ctf_node
*first
;
1173 struct ctf_field_class
*decl
= NULL
;
1174 struct ctf_field_class
*outer_field_decl
= NULL
;
1175 struct bt_list_head
*length
=
1176 &node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.length
;
1178 /* Create array/sequence, pass nested_decl as child */
1179 if (bt_list_empty(length
)) {
1180 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1181 "Expecting length field reference or value.");
1186 first
= _BT_LIST_FIRST_ENTRY(length
, struct ctf_node
, siblings
);
1187 if (first
->type
!= NODE_UNARY_EXPRESSION
) {
1188 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type=%d",
1194 switch (first
->u
.unary_expression
.type
) {
1195 case UNARY_UNSIGNED_CONSTANT
:
1197 struct ctf_field_class_array
*array_decl
= NULL
;
1199 array_decl
= ctf_field_class_array_create();
1200 BT_ASSERT(array_decl
);
1201 array_decl
->length
= first
->u
.unary_expression
.u
.unsigned_constant
;
1202 array_decl
->base
.elem_fc
= nested_decl
;
1204 decl
= &array_decl
->base
.base
;
1209 /* Lookup unsigned integer definition, create seq. */
1210 struct ctf_field_class_sequence
*seq_decl
= NULL
;
1211 char *length_name
= ctf_ast_concatenate_unary_strings(length
);
1214 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1215 "Cannot concatenate unary strings.");
1220 if (strncmp(length_name
, "env.", 4) == 0) {
1221 /* This is, in fact, an array */
1222 const char *env_entry_name
= &length_name
[4];
1223 struct ctf_trace_class_env_entry
*env_entry
=
1224 ctf_trace_class_borrow_env_entry_by_name(ctx
->ctf_tc
, env_entry_name
);
1225 struct ctf_field_class_array
*array_decl
;
1228 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1229 "Cannot find environment entry: "
1236 if (env_entry
->type
!= CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
) {
1237 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1238 "Wrong environment entry type "
1239 "(expecting integer): "
1246 if (env_entry
->value
.i
< 0) {
1247 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1248 "Invalid, negative array length: "
1249 "env-entry-name=\"%s\", "
1251 env_entry_name
, env_entry
->value
.i
);
1256 array_decl
= ctf_field_class_array_create();
1257 BT_ASSERT(array_decl
);
1258 array_decl
->length
= (uint64_t) env_entry
->value
.i
;
1259 array_decl
->base
.elem_fc
= nested_decl
;
1261 decl
= &array_decl
->base
.base
;
1263 seq_decl
= ctf_field_class_sequence_create();
1264 BT_ASSERT(seq_decl
);
1265 seq_decl
->base
.elem_fc
= nested_decl
;
1267 g_string_assign(seq_decl
->length_ref
, length_name
);
1268 decl
= &seq_decl
->base
.base
;
1271 g_free(length_name
);
1279 BT_ASSERT(!nested_decl
);
1281 BT_ASSERT(!*field_decl
);
1284 * At this point, we found the next nested declaration.
1285 * We currently own this (and lost the ownership of
1286 * nested_decl in the meantime). Pass this next
1287 * nested declaration as the content of the outer
1288 * container, MOVING its ownership.
1290 ret
= visit_field_class_declarator(
1291 ctx
, cls_specifier_list
, field_name
,
1292 node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.field_class_declarator
,
1293 &outer_field_decl
, decl
);
1296 BT_ASSERT(!outer_field_decl
);
1301 BT_ASSERT(outer_field_decl
);
1302 *field_decl
= outer_field_decl
;
1303 outer_field_decl
= NULL
;
1306 BT_ASSERT(*field_decl
);
1310 ctf_field_class_destroy(*field_decl
);
1318 ctf_field_class_destroy(nested_decl
);
1323 static int visit_struct_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1324 struct ctf_field_class_struct
*struct_decl
,
1325 struct ctf_node
*cls_specifier_list
,
1326 struct bt_list_head
*field_class_declarators
)
1329 struct ctf_node
*iter
;
1330 struct ctf_field_class
*field_decl
= NULL
;
1332 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1335 const char *field_name
;
1337 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1340 BT_ASSERT(!field_decl
);
1341 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1342 "Cannot visit field class declarator: ret=%d", ret
);
1346 BT_ASSERT(field_decl
);
1347 field_name
= g_quark_to_string(qfield_name
);
1349 /* Check if field with same name already exists */
1350 if (ctf_field_class_struct_borrow_member_by_name(struct_decl
, field_name
)) {
1351 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1352 "Duplicate field in structure field class: "
1353 "field-name=\"%s\"",
1359 /* Add field to structure */
1360 ctf_field_class_struct_append_member(struct_decl
, field_name
, field_decl
);
1367 ctf_field_class_destroy(field_decl
);
1372 static int visit_variant_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1373 struct ctf_field_class_variant
*variant_decl
,
1374 struct ctf_node
*cls_specifier_list
,
1375 struct bt_list_head
*field_class_declarators
)
1378 struct ctf_node
*iter
;
1379 struct ctf_field_class
*field_decl
= NULL
;
1381 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1384 const char *field_name
;
1386 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1389 BT_ASSERT(!field_decl
);
1390 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1391 "Cannot visit field class declarator: ret=%d", ret
);
1395 BT_ASSERT(field_decl
);
1396 field_name
= g_quark_to_string(qfield_name
);
1398 /* Check if field with same name already exists */
1399 if (ctf_field_class_variant_borrow_option_by_name(variant_decl
, field_name
)) {
1400 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1401 "Duplicate field in variant field class: "
1402 "field-name=\"%s\"",
1408 /* Add field to structure */
1409 ctf_field_class_variant_append_option(variant_decl
, field_name
, field_decl
);
1416 ctf_field_class_destroy(field_decl
);
1421 static int visit_field_class_def(struct ctf_visitor_generate_ir
*ctx
,
1422 struct ctf_node
*cls_specifier_list
,
1423 struct bt_list_head
*field_class_declarators
)
1427 struct ctf_node
*iter
;
1428 struct ctf_field_class
*class_decl
= NULL
;
1430 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1431 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qidentifier
, iter
, &class_decl
,
1434 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit field class declarator: ret=%d",
1440 /* Do not allow field class def and alias of untagged variants */
1441 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1442 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1444 if (var_fc
->tag_path
.path
->len
== 0) {
1445 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1446 iter
, "Type definition of untagged variant field class is not allowed.");
1452 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qidentifier
),
1455 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot register field class alias: name=\"%s\"",
1456 g_quark_to_string(qidentifier
));
1462 ctf_field_class_destroy(class_decl
);
1467 static int visit_field_class_alias(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*target
,
1468 struct ctf_node
*alias
)
1472 struct ctf_node
*node
;
1473 GQuark qdummy_field_name
;
1474 struct ctf_field_class
*class_decl
= NULL
;
1476 /* Create target field class */
1477 if (bt_list_empty(&target
->u
.field_class_alias_target
.field_class_declarators
)) {
1480 node
= _BT_LIST_FIRST_ENTRY(&target
->u
.field_class_alias_target
.field_class_declarators
,
1481 struct ctf_node
, siblings
);
1484 ret
= visit_field_class_declarator(
1485 ctx
, target
->u
.field_class_alias_target
.field_class_specifier_list
, &qdummy_field_name
,
1486 node
, &class_decl
, NULL
);
1488 BT_ASSERT(!class_decl
);
1489 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot visit field class declarator: ret=%d", ret
);
1493 /* Do not allow field class def and alias of untagged variants */
1494 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1495 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1497 if (var_fc
->tag_path
.path
->len
== 0) {
1498 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1499 target
, "Type definition of untagged variant field class is not allowed.");
1506 * The semantic validator does not check whether the target is
1507 * abstract or not (if it has an identifier). Check it here.
1509 if (qdummy_field_name
!= 0) {
1510 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target
, "Expecting empty identifier: id=\"%s\"",
1511 g_quark_to_string(qdummy_field_name
));
1516 /* Create alias identifier */
1517 node
= _BT_LIST_FIRST_ENTRY(&alias
->u
.field_class_alias_name
.field_class_declarators
,
1518 struct ctf_node
, siblings
);
1519 qalias
= create_class_alias_identifier(
1520 ctx
, alias
->u
.field_class_alias_name
.field_class_specifier_list
, node
);
1521 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qalias
), class_decl
);
1523 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot register class alias: name=\"%s\"",
1524 g_quark_to_string(qalias
));
1529 ctf_field_class_destroy(class_decl
);
1534 static int visit_struct_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
1535 struct ctf_field_class_struct
*struct_decl
)
1539 switch (entry_node
->type
) {
1541 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1542 &entry_node
->u
.field_class_def
.field_class_declarators
);
1544 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1545 entry_node
, "Cannot add field class found in structure field class: ret=%d", ret
);
1549 case NODE_TYPEALIAS
:
1550 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1551 entry_node
->u
.field_class_alias
.alias
);
1553 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1554 entry_node
, "Cannot add field class alias found in structure field class: ret=%d",
1559 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1561 ret
= visit_struct_decl_field(
1563 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1564 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1570 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
1580 static int visit_variant_decl_entry(struct ctf_visitor_generate_ir
*ctx
,
1581 struct ctf_node
*entry_node
,
1582 struct ctf_field_class_variant
*variant_decl
)
1586 switch (entry_node
->type
) {
1588 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1589 &entry_node
->u
.field_class_def
.field_class_declarators
);
1591 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1592 entry_node
, "Cannot add field class found in variant field class: ret=%d", ret
);
1596 case NODE_TYPEALIAS
:
1597 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1598 entry_node
->u
.field_class_alias
.alias
);
1600 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1601 entry_node
, "Cannot add field class alias found in variant field class: ret=%d",
1606 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1608 ret
= visit_variant_decl_field(
1610 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1611 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1617 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
1627 static int visit_struct_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1628 struct bt_list_head
*decl_list
, int has_body
,
1629 struct bt_list_head
*min_align
,
1630 struct ctf_field_class_struct
**struct_decl
)
1634 BT_ASSERT(struct_decl
);
1635 *struct_decl
= NULL
;
1637 /* For named struct (without body), lookup in declaration scope */
1640 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1641 "Bodyless structure field class: missing name.");
1646 *struct_decl
= ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, -1, true);
1647 if (!*struct_decl
) {
1648 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1649 "Cannot find structure field class: name=\"struct %s\"", name
);
1654 struct ctf_node
*entry_node
;
1655 uint64_t min_align_value
= 0;
1658 if (ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, 1, false)) {
1659 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1660 "Structure field class already declared in local scope: "
1661 "name=\"struct %s\"",
1668 if (!bt_list_empty(min_align
)) {
1669 ret
= get_unary_unsigned(ctx
, min_align
, &min_align_value
);
1671 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1672 "Unexpected unary expression for structure field class's `align` attribute: "
1679 *struct_decl
= ctf_field_class_struct_create();
1680 BT_ASSERT(*struct_decl
);
1682 if (min_align_value
!= 0) {
1683 (*struct_decl
)->base
.alignment
= min_align_value
;
1686 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1688 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1689 ret
= visit_struct_decl_entry(ctx
, entry_node
, *struct_decl
);
1691 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1692 "Cannot visit structure field class entry: "
1703 ret
= ctx_decl_scope_register_struct(ctx
->current_scope
, name
, *struct_decl
);
1705 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1706 "Cannot register structure field class in declaration scope: "
1707 "name=\"struct %s\", ret=%d",
1717 ctf_field_class_destroy(&(*struct_decl
)->base
);
1718 *struct_decl
= NULL
;
1722 static int visit_variant_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1723 const char *tag
, struct bt_list_head
*decl_list
, int has_body
,
1724 struct ctf_field_class_variant
**variant_decl
)
1727 struct ctf_field_class_variant
*untagged_variant_decl
= NULL
;
1729 BT_ASSERT(variant_decl
);
1730 *variant_decl
= NULL
;
1732 /* For named variant (without body), lookup in declaration scope */
1735 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name.");
1740 untagged_variant_decl
= ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, -1, true);
1741 if (!untagged_variant_decl
) {
1742 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1743 "Cannot find variant field class: name=\"variant %s\"", name
);
1748 struct ctf_node
*entry_node
;
1751 if (ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, 1, false)) {
1752 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1753 "Variant field class already declared in local scope: "
1754 "name=\"variant %s\"",
1761 untagged_variant_decl
= ctf_field_class_variant_create();
1762 BT_ASSERT(untagged_variant_decl
);
1763 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1765 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1766 ret
= visit_variant_decl_entry(ctx
, entry_node
, untagged_variant_decl
);
1768 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1769 "Cannot visit variant field class entry: "
1780 ret
= ctx_decl_scope_register_variant(ctx
->current_scope
, name
, untagged_variant_decl
);
1782 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1783 "Cannot register variant field class in declaration scope: "
1784 "name=\"variant %s\", ret=%d",
1792 * If tagged, create tagged variant and return; otherwise
1793 * return untagged variant.
1796 *variant_decl
= untagged_variant_decl
;
1797 untagged_variant_decl
= NULL
;
1800 * At this point, we have a fresh untagged variant; nobody
1801 * else owns it. Set its tag now.
1803 g_string_assign(untagged_variant_decl
->tag_ref
, tag
);
1804 *variant_decl
= untagged_variant_decl
;
1805 untagged_variant_decl
= NULL
;
1808 BT_ASSERT(!untagged_variant_decl
);
1809 BT_ASSERT(*variant_decl
);
1813 ctf_field_class_destroy(&untagged_variant_decl
->base
);
1814 untagged_variant_decl
= NULL
;
1815 ctf_field_class_destroy(&(*variant_decl
)->base
);
1816 *variant_decl
= NULL
;
1830 static int visit_enum_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*enumerator
,
1831 struct ctf_field_class_enum
*enum_decl
, struct uori
*last
)
1835 struct ctf_node
*iter
;
1836 struct uori start
= {
1850 const char *label
= enumerator
->u
.enumerator
.id
;
1851 struct bt_list_head
*values
= &enumerator
->u
.enumerator
.values
;
1853 bt_list_for_each_entry (iter
, values
, siblings
) {
1854 struct uori
*target
;
1856 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
1857 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1858 "Wrong expression for enumeration field class label: "
1859 "node-type=%d, label=\"%s\"",
1871 switch (iter
->u
.unary_expression
.type
) {
1872 case UNARY_SIGNED_CONSTANT
:
1873 target
->is_signed
= true;
1874 target
->value
.i
= iter
->u
.unary_expression
.u
.signed_constant
;
1876 case UNARY_UNSIGNED_CONSTANT
:
1877 target
->is_signed
= false;
1878 target
->value
.u
= iter
->u
.unary_expression
.u
.unsigned_constant
;
1881 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1882 "Invalid enumeration field class entry: "
1883 "expecting constant signed or unsigned integer: "
1884 "node-type=%d, label=\"%s\"",
1885 iter
->u
.unary_expression
.type
, label
);
1891 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1892 iter
, "Invalid enumeration field class entry: label=\"%s\"", label
);
1908 if (end
.is_signed
) {
1909 last
->value
.i
= end
.value
.i
+ 1;
1911 last
->value
.u
= end
.value
.u
+ 1;
1914 ctf_field_class_enum_map_range(enum_decl
, label
, start
.value
.u
, end
.value
.u
);
1921 static int visit_enum_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1922 struct ctf_node
*container_cls
, struct bt_list_head
*enumerator_list
,
1923 int has_body
, struct ctf_field_class_enum
**enum_decl
)
1927 struct ctf_field_class_int
*integer_decl
= NULL
;
1929 BT_ASSERT(enum_decl
);
1932 /* For named enum (without body), lookup in declaration scope */
1935 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1936 "Bodyless enumeration field class: missing name.");
1941 *enum_decl
= ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, -1, true);
1943 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: "
1950 struct ctf_node
*iter
;
1951 struct uori last_value
= {
1960 if (ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, 1, false)) {
1961 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1962 "Enumeration field class already declared in local scope: "
1970 if (!container_cls
) {
1971 integer_decl
= ctf_field_class_as_int(
1972 ctx_decl_scope_lookup_alias(ctx
->current_scope
, "int", -1, true));
1973 if (!integer_decl
) {
1974 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1975 "Cannot find implicit `int` field class alias for enumeration field class.");
1980 ctf_field_class
*decl
;
1982 ret
= visit_field_class_declarator(ctx
, container_cls
, &qdummy_id
, NULL
, &decl
, NULL
);
1989 integer_decl
= ctf_field_class_as_int(decl
);
1992 BT_ASSERT(integer_decl
);
1994 if (integer_decl
->base
.base
.type
!= CTF_FIELD_CLASS_TYPE_INT
) {
1995 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1996 "Container field class for enumeration field class is not an integer field class: "
1998 integer_decl
->base
.base
.type
);
2003 *enum_decl
= ctf_field_class_enum_create();
2004 BT_ASSERT(*enum_decl
);
2005 (*enum_decl
)->base
.base
.base
.alignment
= integer_decl
->base
.base
.alignment
;
2006 ctf_field_class_int_copy_content(&(*enum_decl
)->base
, integer_decl
);
2007 last_value
.is_signed
= (*enum_decl
)->base
.is_signed
;
2009 bt_list_for_each_entry (iter
, enumerator_list
, siblings
) {
2010 ret
= visit_enum_decl_entry(ctx
, iter
, *enum_decl
, &last_value
);
2012 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
2013 "Cannot visit enumeration field class entry: "
2021 ret
= ctx_decl_scope_register_enum(ctx
->current_scope
, name
, *enum_decl
);
2023 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2024 "Cannot register enumeration field class in declaration scope: "
2035 ctf_field_class_destroy(&(*enum_decl
)->base
.base
.base
);
2039 ctf_field_class_destroy(&integer_decl
->base
.base
);
2040 integer_decl
= NULL
;
2044 static int visit_field_class_specifier(struct ctf_visitor_generate_ir
*ctx
,
2045 struct ctf_node
*cls_specifier_list
,
2046 struct ctf_field_class
**decl
)
2049 GString
*str
= NULL
;
2052 str
= g_string_new("");
2053 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
2055 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2056 cls_specifier_list
, "Cannot get field class specifier list's name: ret=%d", ret
);
2060 *decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, str
->str
, -1, true);
2062 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2063 "Cannot find field class alias: name=\"%s\"", str
->str
);
2071 ctf_field_class_destroy(*decl
);
2076 g_string_free(str
, TRUE
);
2082 static int visit_integer_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2083 struct ctf_field_class_int
**integer_decl
)
2088 struct ctf_node
*expression
;
2089 uint64_t alignment
= 0, size
= 0;
2090 struct ctf_clock_class
*mapped_clock_class
= NULL
;
2091 enum ctf_encoding encoding
= CTF_ENCODING_NONE
;
2092 bt_field_class_integer_preferred_display_base base
=
2093 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2094 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2096 *integer_decl
= NULL
;
2098 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2099 struct ctf_node
*left
, *right
;
2101 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2103 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2105 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2106 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2107 left
->u
.unary_expression
.type
);
2112 if (strcmp(left
->u
.unary_expression
.u
.string
, "signed") == 0) {
2113 if (_IS_SET(&set
, _INTEGER_SIGNED_SET
)) {
2114 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "signed", "integer field class");
2119 signedness
= get_boolean(ctx
, right
);
2120 if (signedness
< 0) {
2121 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2123 "Invalid boolean value for integer field class's `signed` attribute: "
2130 _SET(&set
, _INTEGER_SIGNED_SET
);
2131 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2132 if (_IS_SET(&set
, _INTEGER_BYTE_ORDER_SET
)) {
2133 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order", "integer field class");
2138 byte_order
= get_real_byte_order(ctx
, right
);
2139 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2140 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2142 "Invalid `byte_order` attribute in integer field class: "
2149 _SET(&set
, _INTEGER_BYTE_ORDER_SET
);
2150 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "size") == 0) {
2151 if (_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2152 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "size", "integer field class");
2157 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2158 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2159 "Invalid `size` attribute in integer field class: "
2160 "expecting unsigned constant integer: "
2162 right
->u
.unary_expression
.type
);
2167 size
= right
->u
.unary_expression
.u
.unsigned_constant
;
2169 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2170 "Invalid `size` attribute in integer field class: "
2171 "expecting positive constant integer: "
2176 } else if (size
> 64) {
2177 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2179 "Invalid `size` attribute in integer field class: "
2180 "integer fields over 64 bits are not supported as of this version: "
2187 _SET(&set
, _INTEGER_SIZE_SET
);
2188 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2189 if (_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2190 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align", "integer field class");
2195 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2196 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2197 "Invalid `align` attribute in integer field class: "
2198 "expecting unsigned constant integer: "
2200 right
->u
.unary_expression
.type
);
2205 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2206 if (!is_align_valid(alignment
)) {
2207 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2208 "Invalid `align` attribute in integer field class: "
2209 "expecting power of two: "
2216 _SET(&set
, _INTEGER_ALIGN_SET
);
2217 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "base") == 0) {
2218 if (_IS_SET(&set
, _INTEGER_BASE_SET
)) {
2219 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "base", "integer field class");
2224 switch (right
->u
.unary_expression
.type
) {
2225 case UNARY_UNSIGNED_CONSTANT
:
2227 uint64_t constant
= right
->u
.unary_expression
.u
.unsigned_constant
;
2231 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2234 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2237 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2240 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2243 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2245 "Invalid `base` attribute in integer field class: "
2247 right
->u
.unary_expression
.u
.unsigned_constant
);
2256 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2258 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2260 "Unexpected unary expression for integer field class's `base` attribute.");
2265 if (strcmp(s_right
, "decimal") == 0 || strcmp(s_right
, "dec") == 0 ||
2266 strcmp(s_right
, "d") == 0 || strcmp(s_right
, "i") == 0 ||
2267 strcmp(s_right
, "u") == 0) {
2268 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2269 } else if (strcmp(s_right
, "hexadecimal") == 0 || strcmp(s_right
, "hex") == 0 ||
2270 strcmp(s_right
, "x") == 0 || strcmp(s_right
, "X") == 0 ||
2271 strcmp(s_right
, "p") == 0) {
2272 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2273 } else if (strcmp(s_right
, "octal") == 0 || strcmp(s_right
, "oct") == 0 ||
2274 strcmp(s_right
, "o") == 0) {
2275 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2276 } else if (strcmp(s_right
, "binary") == 0 || strcmp(s_right
, "b") == 0) {
2277 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2279 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2281 "Unexpected unary expression for integer field class's `base` attribute: "
2293 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2294 right
, "Invalid `base` attribute in integer field class: "
2295 "expecting unsigned constant integer or unary string.");
2300 _SET(&set
, _INTEGER_BASE_SET
);
2301 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2304 if (_IS_SET(&set
, _INTEGER_ENCODING_SET
)) {
2305 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "integer field class");
2310 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2311 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2312 right
, "Invalid `encoding` attribute in integer field class: "
2313 "expecting unary string.");
2318 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2320 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2322 "Unexpected unary expression for integer field class's `encoding` attribute.");
2327 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2328 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2329 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2330 encoding
= CTF_ENCODING_UTF8
;
2331 } else if (strcmp(s_right
, "none") == 0) {
2332 encoding
= CTF_ENCODING_NONE
;
2334 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2336 "Invalid `encoding` attribute in integer field class: "
2337 "unknown encoding: encoding=\"%s\"",
2345 _SET(&set
, _INTEGER_ENCODING_SET
);
2346 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "map") == 0) {
2347 const char *clock_name
;
2349 if (_IS_SET(&set
, _INTEGER_MAP_SET
)) {
2350 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "map", "integer field class");
2355 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2356 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2357 "Invalid `map` attribute in integer field class: "
2358 "expecting unary string.");
2363 clock_name
= get_map_clock_name_value(&expression
->u
.ctf_expression
.right
);
2366 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2369 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2371 "Unexpected unary expression for integer field class's `map` attribute.");
2376 _BT_COMP_LOGE_NODE(right
,
2377 "Invalid `map` attribute in integer field class: "
2378 "cannot find clock class at this point: name=\"%s\"",
2380 _SET(&set
, _INTEGER_MAP_SET
);
2385 mapped_clock_class
=
2386 ctf_trace_class_borrow_clock_class_by_name(ctx
->ctf_tc
, clock_name
);
2387 if (!mapped_clock_class
) {
2388 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2390 "Invalid `map` attribute in integer field class: "
2391 "cannot find clock class at this point: name=\"%s\"",
2397 _SET(&set
, _INTEGER_MAP_SET
);
2399 _BT_COMP_LOGW_NODE(left
,
2400 "Unknown attribute in integer field class: "
2402 left
->u
.unary_expression
.u
.string
);
2406 if (!_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2407 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2408 "Missing `size` attribute in integer field class.");
2413 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2414 if (size
% CHAR_BIT
) {
2415 /* Bit-packed alignment */
2418 /* Byte-packed alignment */
2419 alignment
= CHAR_BIT
;
2423 *integer_decl
= ctf_field_class_int_create();
2424 BT_ASSERT(*integer_decl
);
2425 (*integer_decl
)->base
.base
.alignment
= alignment
;
2426 (*integer_decl
)->base
.byte_order
= byte_order
;
2427 (*integer_decl
)->base
.size
= size
;
2428 (*integer_decl
)->is_signed
= (signedness
> 0);
2429 (*integer_decl
)->disp_base
= base
;
2430 (*integer_decl
)->encoding
= encoding
;
2431 (*integer_decl
)->mapped_clock_class
= mapped_clock_class
;
2435 ctf_field_class_destroy(&(*integer_decl
)->base
.base
);
2436 *integer_decl
= NULL
;
2440 static int visit_floating_point_number_decl(struct ctf_visitor_generate_ir
*ctx
,
2441 struct bt_list_head
*expressions
,
2442 struct ctf_field_class_float
**float_decl
)
2446 struct ctf_node
*expression
;
2447 uint64_t alignment
= 1, exp_dig
= 0, mant_dig
= 0;
2448 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2452 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2453 struct ctf_node
*left
, *right
;
2455 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2457 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2459 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2460 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2461 left
->u
.unary_expression
.type
);
2466 if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2467 if (_IS_SET(&set
, _FLOAT_BYTE_ORDER_SET
)) {
2468 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order",
2469 "floating point number field class");
2474 byte_order
= get_real_byte_order(ctx
, right
);
2475 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2476 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2478 "Invalid `byte_order` attribute in floating point number field class: "
2485 _SET(&set
, _FLOAT_BYTE_ORDER_SET
);
2486 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "exp_dig") == 0) {
2487 if (_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2488 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "exp_dig",
2489 "floating point number field class");
2494 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2495 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2497 "Invalid `exp_dig` attribute in floating point number field class: "
2498 "expecting unsigned constant integer: "
2500 right
->u
.unary_expression
.type
);
2505 exp_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2506 _SET(&set
, _FLOAT_EXP_DIG_SET
);
2507 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "mant_dig") == 0) {
2508 if (_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2509 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "mant_dig",
2510 "floating point number field class");
2515 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2516 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2518 "Invalid `mant_dig` attribute in floating point number field class: "
2519 "expecting unsigned constant integer: "
2521 right
->u
.unary_expression
.type
);
2526 mant_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2527 _SET(&set
, _FLOAT_MANT_DIG_SET
);
2528 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2529 if (_IS_SET(&set
, _FLOAT_ALIGN_SET
)) {
2530 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align",
2531 "floating point number field class");
2536 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2537 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2539 "Invalid `align` attribute in floating point number field class: "
2540 "expecting unsigned constant integer: "
2542 right
->u
.unary_expression
.type
);
2547 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2549 if (!is_align_valid(alignment
)) {
2550 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2552 "Invalid `align` attribute in floating point number field class: "
2553 "expecting power of two: "
2560 _SET(&set
, _FLOAT_ALIGN_SET
);
2562 _BT_COMP_LOGW_NODE(left
,
2563 "Unknown attribute in floating point number field class: "
2565 left
->u
.unary_expression
.u
.string
);
2569 if (!_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2570 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2571 "Missing `mant_dig` attribute in floating point number field class.");
2576 if (!_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2577 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2578 "Missing `exp_dig` attribute in floating point number field class.");
2583 if (mant_dig
!= 24 && mant_dig
!= 53) {
2584 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53.");
2589 if (mant_dig
== 24 && exp_dig
!= 8) {
2590 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2591 "`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2596 if (mant_dig
== 53 && exp_dig
!= 11) {
2597 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2598 "`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2603 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2604 if ((mant_dig
+ exp_dig
) % CHAR_BIT
) {
2605 /* Bit-packed alignment */
2608 /* Byte-packed alignment */
2609 alignment
= CHAR_BIT
;
2613 *float_decl
= ctf_field_class_float_create();
2614 BT_ASSERT(*float_decl
);
2615 (*float_decl
)->base
.base
.alignment
= alignment
;
2616 (*float_decl
)->base
.byte_order
= byte_order
;
2617 (*float_decl
)->base
.size
= mant_dig
+ exp_dig
;
2621 ctf_field_class_destroy(&(*float_decl
)->base
.base
);
2626 static int visit_string_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2627 struct ctf_field_class_string
**string_decl
)
2631 struct ctf_node
*expression
;
2632 enum ctf_encoding encoding
= CTF_ENCODING_UTF8
;
2634 *string_decl
= NULL
;
2636 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2637 struct ctf_node
*left
, *right
;
2639 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2641 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2643 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2644 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2645 left
->u
.unary_expression
.type
);
2650 if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2653 if (_IS_SET(&set
, _STRING_ENCODING_SET
)) {
2654 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "string field class");
2659 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2660 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2661 right
, "Invalid `encoding` attribute in string field class: "
2662 "expecting unary string.");
2667 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2669 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2671 "Unexpected unary expression for string field class's `encoding` attribute.");
2676 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2677 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2678 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2679 encoding
= CTF_ENCODING_UTF8
;
2680 } else if (strcmp(s_right
, "none") == 0) {
2681 encoding
= CTF_ENCODING_NONE
;
2683 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2685 "Invalid `encoding` attribute in string field class: "
2686 "unknown encoding: encoding=\"%s\"",
2694 _SET(&set
, _STRING_ENCODING_SET
);
2696 _BT_COMP_LOGW_NODE(left
,
2697 "Unknown attribute in string field class: "
2699 left
->u
.unary_expression
.u
.string
);
2703 *string_decl
= ctf_field_class_string_create();
2704 BT_ASSERT(*string_decl
);
2705 (*string_decl
)->encoding
= encoding
;
2709 ctf_field_class_destroy(&(*string_decl
)->base
);
2710 *string_decl
= NULL
;
2714 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
2715 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
)
2718 struct ctf_node
*first
, *node
;
2722 if (ts_list
->type
!= NODE_TYPE_SPECIFIER_LIST
) {
2723 _BT_COMP_LOGE_APPEND_CAUSE_NODE(ts_list
, "Unexpected node type: node-type=%d",
2729 first
= _BT_LIST_FIRST_ENTRY(&ts_list
->u
.field_class_specifier_list
.head
, struct ctf_node
,
2731 if (first
->type
!= NODE_TYPE_SPECIFIER
) {
2732 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type=%d", first
->type
);
2737 node
= first
->u
.field_class_specifier
.node
;
2739 switch (first
->u
.field_class_specifier
.type
) {
2740 case TYPESPEC_INTEGER
:
2742 ctf_field_class_int
*int_decl
;
2744 ret
= visit_integer_decl(ctx
, &node
->u
.integer
.expressions
, &int_decl
);
2746 BT_ASSERT(!int_decl
);
2750 *decl
= &int_decl
->base
.base
;
2753 case TYPESPEC_FLOATING_POINT
:
2755 ctf_field_class_float
*float_decl
;
2758 visit_floating_point_number_decl(ctx
, &node
->u
.floating_point
.expressions
, &float_decl
);
2760 BT_ASSERT(!float_decl
);
2764 *decl
= &float_decl
->base
.base
;
2767 case TYPESPEC_STRING
:
2769 ctf_field_class_string
*string_decl
;
2771 ret
= visit_string_decl(ctx
, &node
->u
.string
.expressions
, &string_decl
);
2773 BT_ASSERT(!string_decl
);
2777 *decl
= &string_decl
->base
;
2780 case TYPESPEC_STRUCT
:
2782 ctf_field_class_struct
*struct_decl
;
2784 ret
= visit_struct_decl(ctx
, node
->u
._struct
.name
, &node
->u
._struct
.declaration_list
,
2785 node
->u
._struct
.has_body
, &node
->u
._struct
.min_align
, &struct_decl
);
2787 BT_ASSERT(!struct_decl
);
2791 *decl
= &struct_decl
->base
;
2794 case TYPESPEC_VARIANT
:
2796 ctf_field_class_variant
*variant_decl
;
2798 ret
= visit_variant_decl(ctx
, node
->u
.variant
.name
, node
->u
.variant
.choice
,
2799 &node
->u
.variant
.declaration_list
, node
->u
.variant
.has_body
,
2802 BT_ASSERT(!variant_decl
);
2806 *decl
= &variant_decl
->base
;
2811 ctf_field_class_enum
*enum_decl
;
2813 ret
= visit_enum_decl(ctx
, node
->u
._enum
.enum_id
, node
->u
._enum
.container_field_class
,
2814 &node
->u
._enum
.enumerator_list
, node
->u
._enum
.has_body
, &enum_decl
);
2816 BT_ASSERT(!enum_decl
);
2820 *decl
= &enum_decl
->base
.base
.base
;
2825 case TYPESPEC_SHORT
:
2828 case TYPESPEC_FLOAT
:
2829 case TYPESPEC_DOUBLE
:
2830 case TYPESPEC_SIGNED
:
2831 case TYPESPEC_UNSIGNED
:
2833 case TYPESPEC_COMPLEX
:
2834 case TYPESPEC_IMAGINARY
:
2835 case TYPESPEC_CONST
:
2836 case TYPESPEC_ID_TYPE
:
2837 ret
= visit_field_class_specifier(ctx
, ts_list
, decl
);
2839 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Cannot visit field class specifier: ret=%d",
2846 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
,
2847 "Unexpected field class specifier type: node-type=%d",
2848 first
->u
.field_class_specifier
.type
);
2857 ctf_field_class_destroy(*decl
);
2862 static int visit_event_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
2863 struct ctf_event_class
*event_class
, uint64_t *stream_id
,
2869 switch (node
->type
) {
2871 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
2872 &node
->u
.field_class_def
.field_class_declarators
);
2874 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in event class.");
2878 case NODE_TYPEALIAS
:
2879 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
2880 node
->u
.field_class_alias
.alias
);
2882 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2883 "Cannot add field class alias found in event class.");
2887 case NODE_CTF_EXPRESSION
:
2889 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
2891 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
2896 if (strcmp(left
, "name") == 0) {
2897 /* This is already known at this stage */
2898 if (_IS_SET(set
, _EVENT_NAME_SET
)) {
2899 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "name", "event class");
2904 _SET(set
, _EVENT_NAME_SET
);
2905 } else if (strcmp(left
, "id") == 0) {
2908 if (_IS_SET(set
, _EVENT_ID_SET
)) {
2909 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "event class");
2914 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
2915 /* Only read "id" if get_unary_unsigned() succeeded. */
2916 if (ret
|| (!ret
&& id
< 0)) {
2917 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2918 node
, "Unexpected unary expression for event class's `id` attribute.");
2923 event_class
->id
= id
;
2924 _SET(set
, _EVENT_ID_SET
);
2925 } else if (strcmp(left
, "stream_id") == 0) {
2926 if (_IS_SET(set
, _EVENT_STREAM_ID_SET
)) {
2927 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "stream_id", "event class");
2932 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, stream_id
);
2935 * Only read "stream_id" if get_unary_unsigned()
2939 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2940 node
, "Unexpected unary expression for event class's `stream_id` attribute.");
2945 _SET(set
, _EVENT_STREAM_ID_SET
);
2946 } else if (strcmp(left
, "context") == 0) {
2947 if (_IS_SET(set
, _EVENT_CONTEXT_SET
)) {
2948 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `context` entry in event class.");
2953 ret
= visit_field_class_specifier_list(
2954 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2955 &event_class
->spec_context_fc
);
2957 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2958 "Cannot create event class's context field class.");
2962 BT_ASSERT(event_class
->spec_context_fc
);
2963 _SET(set
, _EVENT_CONTEXT_SET
);
2964 } else if (strcmp(left
, "fields") == 0) {
2965 if (_IS_SET(set
, _EVENT_FIELDS_SET
)) {
2966 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `fields` entry in event class.");
2971 ret
= visit_field_class_specifier_list(
2972 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2973 &event_class
->payload_fc
);
2975 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2976 "Cannot create event class's payload field class.");
2980 BT_ASSERT(event_class
->payload_fc
);
2981 _SET(set
, _EVENT_FIELDS_SET
);
2982 } else if (strcmp(left
, "loglevel") == 0) {
2983 uint64_t loglevel_value
;
2984 bool is_log_level_known
= true;
2985 bt_event_class_log_level log_level
;
2987 if (_IS_SET(set
, _EVENT_LOG_LEVEL_SET
)) {
2988 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "loglevel", "event class");
2993 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &loglevel_value
);
2995 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2996 node
, "Unexpected unary expression for event class's `loglevel` attribute.");
3001 switch (loglevel_value
) {
3003 log_level
= BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
;
3006 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ALERT
;
3009 log_level
= BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
;
3012 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ERROR
;
3015 log_level
= BT_EVENT_CLASS_LOG_LEVEL_WARNING
;
3018 log_level
= BT_EVENT_CLASS_LOG_LEVEL_NOTICE
;
3021 log_level
= BT_EVENT_CLASS_LOG_LEVEL_INFO
;
3024 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
;
3027 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
;
3030 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
;
3033 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
;
3036 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
;
3039 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
;
3042 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
;
3045 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG
;
3048 is_log_level_known
= false;
3051 "Not setting event class's log level because its value is unknown: "
3052 "log-level=%" PRIu64
,
3056 if (is_log_level_known
) {
3057 ctf_event_class_set_log_level(event_class
, log_level
);
3060 _SET(set
, _EVENT_LOG_LEVEL_SET
);
3061 } else if (strcmp(left
, "model.emf.uri") == 0) {
3064 if (_IS_SET(set
, _EVENT_MODEL_EMF_URI_SET
)) {
3065 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "model.emf.uri", "event class");
3070 right
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.right
);
3072 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3074 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3079 if (strlen(right
) == 0) {
3080 _BT_COMP_LOGW_NODE(node
, "Not setting event class's EMF URI because it's empty.");
3082 g_string_assign(event_class
->emf_uri
, right
);
3086 _SET(set
, _EVENT_MODEL_EMF_URI_SET
);
3088 _BT_COMP_LOGW_NODE(node
,
3089 "Unknown attribute in event class: "
3112 static char *get_event_decl_name(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3116 struct ctf_node
*iter
;
3117 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3119 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3120 if (iter
->type
!= NODE_CTF_EXPRESSION
) {
3124 left
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.left
);
3126 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot concatenate unary strings.");
3130 if (strcmp(left
, "name") == 0) {
3131 name
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.right
);
3133 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3134 iter
, "Unexpected unary expression for event class's `name` attribute.");
3154 static int visit_event_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3158 struct ctf_node
*iter
;
3159 uint64_t stream_id
= 0;
3160 char *event_name
= NULL
;
3161 struct ctf_event_class
*event_class
= NULL
;
3162 struct ctf_stream_class
*stream_class
= NULL
;
3163 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3164 bool pop_scope
= false;
3166 if (node
->visited
) {
3170 node
->visited
= TRUE
;
3171 event_name
= get_event_decl_name(ctx
, node
);
3173 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `name` attribute in event class.");
3178 event_class
= ctf_event_class_create();
3179 BT_ASSERT(event_class
);
3180 g_string_assign(event_class
->name
, event_name
);
3181 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3184 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3185 ret
= visit_event_decl_entry(ctx
, iter
, event_class
, &stream_id
, &set
);
3187 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3188 "Cannot visit event class's entry: "
3195 if (!_IS_SET(&set
, _EVENT_STREAM_ID_SET
)) {
3197 * Allow missing stream_id if there is only a single
3200 switch (ctx
->ctf_tc
->stream_classes
->len
) {
3202 /* Create implicit stream class if there's none */
3204 stream_class
= ctf_stream_class_create();
3205 BT_ASSERT(stream_class
);
3206 stream_class
->id
= stream_id
;
3207 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3210 /* Single stream class: get its ID */
3211 stream_class
= (ctf_stream_class
*) ctx
->ctf_tc
->stream_classes
->pdata
[0];
3212 stream_id
= stream_class
->id
;
3215 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `stream_id` attribute in event class.");
3221 /* We have the stream ID now; get the stream class if found */
3222 if (!stream_class
) {
3223 stream_class
= ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_id
);
3224 if (!stream_class
) {
3225 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3226 "Cannot find stream class at this point: "
3234 BT_ASSERT(stream_class
);
3236 if (!_IS_SET(&set
, _EVENT_ID_SET
)) {
3237 /* Allow only one event without ID per stream */
3238 if (stream_class
->event_classes
->len
!= 0) {
3239 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `id` attribute in event class.");
3245 event_class
->id
= 0;
3248 if (ctf_stream_class_borrow_event_class_by_id(stream_class
, event_class
->id
)) {
3249 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3250 "Duplicate event class (same ID) in the same stream class: "
3257 ctf_stream_class_append_event_class(stream_class
, event_class
);
3262 ctf_event_class_destroy(event_class
);
3279 static int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3280 struct ctf_field_class
*fc
)
3282 struct ctf_clock_class
*clock_class_to_map_to
= NULL
;
3283 uint64_t clock_class_count
;
3289 if (fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&& fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3293 ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
3295 if (int_fc
->mapped_clock_class
) {
3296 /* Already mapped */
3300 clock_class_count
= ctx
->ctf_tc
->clock_classes
->len
;
3302 switch (clock_class_count
) {
3305 * No clock class exists in the trace at this point. Create an
3306 * implicit one at 1 GHz, named `default`, and use this clock
3309 clock_class_to_map_to
= ctf_clock_class_create();
3310 BT_ASSERT(clock_class_to_map_to
);
3311 clock_class_to_map_to
->frequency
= UINT64_C(1000000000);
3312 g_string_assign(clock_class_to_map_to
->name
, "default");
3313 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock_class_to_map_to
);
3317 * Only one clock class exists in the trace at this point: use
3320 clock_class_to_map_to
= (ctf_clock_class
*) ctx
->ctf_tc
->clock_classes
->pdata
[0];
3324 * Timestamp field not mapped to a clock class and there's more
3325 * than one clock class in the trace: this is an error.
3327 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3328 "Timestamp field found with no mapped clock class, "
3329 "but there's more than one clock class in the trace at this point.");
3333 BT_ASSERT(clock_class_to_map_to
);
3334 int_fc
->mapped_clock_class
= clock_class_to_map_to
;
3339 static int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3340 struct ctf_field_class
*root_fc
,
3341 const char *field_name
)
3345 struct ctf_field_class_struct
*struct_fc
= (ctf_field_class_struct
*) root_fc
;
3346 struct ctf_field_class_variant
*var_fc
= (ctf_field_class_variant
*) root_fc
;
3352 if (root_fc
->type
!= CTF_FIELD_CLASS_TYPE_STRUCT
&&
3353 root_fc
->type
!= CTF_FIELD_CLASS_TYPE_VARIANT
) {
3357 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3358 count
= struct_fc
->members
->len
;
3360 count
= var_fc
->options
->len
;
3363 for (i
= 0; i
< count
; i
++) {
3364 struct ctf_named_field_class
*named_fc
= NULL
;
3366 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3367 named_fc
= ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
3368 } else if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
3369 named_fc
= ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
3374 if (strcmp(named_fc
->name
->str
, field_name
) == 0) {
3375 ret
= auto_map_field_to_trace_clock_class(ctx
, named_fc
->fc
);
3377 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3378 "Cannot automatically map field to trace's clock class: "
3379 "field-name=\"%s\"",
3385 ret
= auto_map_fields_to_trace_clock_class(ctx
, named_fc
->fc
, field_name
);
3387 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3388 "Cannot automatically map structure or variant field class's fields to trace's clock class: "
3389 "field-name=\"%s\", root-field-name=\"%s\"",
3390 field_name
, named_fc
->name
->str
);
3399 static int visit_stream_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3400 struct ctf_stream_class
*stream_class
, int *set
)
3405 switch (node
->type
) {
3407 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3408 &node
->u
.field_class_def
.field_class_declarators
);
3410 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in stream class.");
3414 case NODE_TYPEALIAS
:
3415 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3416 node
->u
.field_class_alias
.alias
);
3418 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3419 "Cannot add field class alias found in stream class.");
3423 case NODE_CTF_EXPRESSION
:
3425 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3427 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3432 if (strcmp(left
, "id") == 0) {
3435 if (_IS_SET(set
, _STREAM_ID_SET
)) {
3436 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "stream declaration");
3441 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
3443 /* Only read "id" if get_unary_unsigned() succeeded. */
3444 if (ret
|| (!ret
&& id
< 0)) {
3445 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3446 node
, "Unexpected unary expression for stream class's `id` attribute.");
3451 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, id
)) {
3452 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3453 node
, "Duplicate stream class (same ID): id=%" PRId64
, id
);
3458 stream_class
->id
= id
;
3459 _SET(set
, _STREAM_ID_SET
);
3460 } else if (strcmp(left
, "event.header") == 0) {
3461 if (_IS_SET(set
, _STREAM_EVENT_HEADER_SET
)) {
3462 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3463 "Duplicate `event.header` entry in stream class.");
3468 ret
= visit_field_class_specifier_list(
3469 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3470 &stream_class
->event_header_fc
);
3472 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3473 node
, "Cannot create stream class's event header field class.");
3477 BT_ASSERT(stream_class
->event_header_fc
);
3478 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->event_header_fc
,
3481 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3483 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3487 _SET(set
, _STREAM_EVENT_HEADER_SET
);
3488 } else if (strcmp(left
, "event.context") == 0) {
3489 if (_IS_SET(set
, _STREAM_EVENT_CONTEXT_SET
)) {
3490 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3491 "Duplicate `event.context` entry in stream class.");
3496 ret
= visit_field_class_specifier_list(
3497 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3498 &stream_class
->event_common_context_fc
);
3500 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3501 node
, "Cannot create stream class's event context field class.");
3505 BT_ASSERT(stream_class
->event_common_context_fc
);
3506 _SET(set
, _STREAM_EVENT_CONTEXT_SET
);
3507 } else if (strcmp(left
, "packet.context") == 0) {
3508 if (_IS_SET(set
, _STREAM_PACKET_CONTEXT_SET
)) {
3509 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3510 node
, "Duplicate `packet.context` entry in stream class.");
3515 ret
= visit_field_class_specifier_list(
3516 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3517 &stream_class
->packet_context_fc
);
3519 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3520 node
, "Cannot create stream class's packet context field class.");
3524 BT_ASSERT(stream_class
->packet_context_fc
);
3525 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3528 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3530 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3534 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3537 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3539 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3543 _SET(set
, _STREAM_PACKET_CONTEXT_SET
);
3545 _BT_COMP_LOGW_NODE(node
,
3546 "Unknown attribute in stream class: "
3568 static int visit_stream_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3572 struct ctf_node
*iter
;
3573 struct ctf_stream_class
*stream_class
= NULL
;
3574 struct bt_list_head
*decl_list
= &node
->u
.stream
.declaration_list
;
3576 if (node
->visited
) {
3580 node
->visited
= TRUE
;
3581 stream_class
= ctf_stream_class_create();
3582 BT_ASSERT(stream_class
);
3583 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3585 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3586 ret
= visit_stream_decl_entry(ctx
, iter
, stream_class
, &set
);
3588 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3589 "Cannot visit stream class's entry: "
3599 if (_IS_SET(&set
, _STREAM_ID_SET
)) {
3600 /* Check that packet header has `stream_id` field */
3601 struct ctf_named_field_class
*named_fc
= NULL
;
3603 if (!ctx
->ctf_tc
->packet_header_fc
) {
3604 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Stream class has a `id` attribute, "
3605 "but trace has no packet header field class.");
3610 named_fc
= ctf_field_class_struct_borrow_member_by_name(
3611 ctf_field_class_as_struct(ctx
->ctf_tc
->packet_header_fc
), "stream_id");
3613 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3614 node
, "Stream class has a `id` attribute, "
3615 "but trace's packet header field class has no `stream_id` field.");
3620 if (named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3621 named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3622 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3624 "Stream class has a `id` attribute, "
3625 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3630 /* Allow only _one_ ID-less stream */
3631 if (ctx
->ctf_tc
->stream_classes
->len
!= 0) {
3632 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3634 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3639 /* Automatic ID: 0 */
3640 stream_class
->id
= 0;
3644 * Make sure that this stream class's ID is currently unique in
3647 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_class
->id
)) {
3648 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate stream class (same ID): id=%" PRId64
,
3654 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3655 stream_class
= NULL
;
3659 ctf_stream_class_destroy(stream_class
);
3660 stream_class
= NULL
;
3666 static int visit_trace_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3673 switch (node
->type
) {
3675 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3676 &node
->u
.field_class_def
.field_class_declarators
);
3678 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3679 node
, "Cannot add field class found in trace (`trace` block).");
3683 case NODE_TYPEALIAS
:
3684 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3685 node
->u
.field_class_alias
.alias
);
3687 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3688 node
, "Cannot add field class alias found in trace (`trace` block).");
3692 case NODE_CTF_EXPRESSION
:
3694 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3696 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3701 if (strcmp(left
, "major") == 0) {
3702 if (_IS_SET(set
, _TRACE_MAJOR_SET
)) {
3703 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "major", "trace");
3708 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3710 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3711 node
, "Unexpected unary expression for trace's `major` attribute.");
3717 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3718 "Invalid trace's `minor` attribute: expecting 1.");
3723 ctx
->ctf_tc
->major
= val
;
3724 _SET(set
, _TRACE_MAJOR_SET
);
3725 } else if (strcmp(left
, "minor") == 0) {
3726 if (_IS_SET(set
, _TRACE_MINOR_SET
)) {
3727 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "minor", "trace");
3732 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3734 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3735 node
, "Unexpected unary expression for trace's `minor` attribute.");
3741 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3742 "Invalid trace's `minor` attribute: expecting 8.");
3747 ctx
->ctf_tc
->minor
= val
;
3748 _SET(set
, _TRACE_MINOR_SET
);
3749 } else if (strcmp(left
, "uuid") == 0) {
3750 if (_IS_SET(set
, _TRACE_UUID_SET
)) {
3751 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "uuid", "trace");
3756 ret
= get_unary_uuid(ctx
, &node
->u
.ctf_expression
.right
, ctx
->ctf_tc
->uuid
);
3758 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid trace's `uuid` attribute.");
3762 ctx
->ctf_tc
->is_uuid_set
= true;
3763 _SET(set
, _TRACE_UUID_SET
);
3764 } else if (strcmp(left
, "byte_order") == 0) {
3765 /* Default byte order is already known at this stage */
3766 if (_IS_SET(set
, _TRACE_BYTE_ORDER_SET
)) {
3767 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
3772 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
!= CTF_BYTE_ORDER_UNKNOWN
);
3773 _SET(set
, _TRACE_BYTE_ORDER_SET
);
3774 } else if (strcmp(left
, "packet.header") == 0) {
3775 if (_IS_SET(set
, _TRACE_PACKET_HEADER_SET
)) {
3776 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `packet.header` entry in trace.");
3781 ret
= visit_field_class_specifier_list(
3782 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3783 &ctx
->ctf_tc
->packet_header_fc
);
3785 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3786 "Cannot create trace's packet header field class.");
3790 BT_ASSERT(ctx
->ctf_tc
->packet_header_fc
);
3791 _SET(set
, _TRACE_PACKET_HEADER_SET
);
3793 _BT_COMP_LOGW_NODE(node
,
3794 "Unknown attribute in stream class: "
3804 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unknown expression in trace.");
3816 static int visit_trace_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3820 struct ctf_node
*iter
;
3821 struct bt_list_head
*decl_list
= &node
->u
.trace
.declaration_list
;
3823 if (node
->visited
) {
3827 node
->visited
= TRUE
;
3829 if (ctx
->is_trace_visited
) {
3830 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
3835 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3837 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3838 ret
= visit_trace_decl_entry(ctx
, iter
, &set
);
3840 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3841 "Cannot visit trace's entry (`trace` block): "
3851 if (!_IS_SET(&set
, _TRACE_MAJOR_SET
)) {
3852 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3853 "Missing `major` attribute in trace (`trace` block).");
3858 if (!_IS_SET(&set
, _TRACE_MINOR_SET
)) {
3859 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3860 "Missing `minor` attribute in trace (`trace` block).");
3865 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3866 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3867 "Missing `byte_order` attribute in trace (`trace` block).");
3872 ctx
->is_trace_visited
= true;
3881 static int visit_env(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3885 struct ctf_node
*entry_node
;
3886 struct bt_list_head
*decl_list
= &node
->u
.env
.declaration_list
;
3888 if (node
->visited
) {
3892 node
->visited
= TRUE
;
3894 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
3895 struct bt_list_head
*right_head
= &entry_node
->u
.ctf_expression
.right
;
3897 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
3898 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
3899 "Wrong expression in environment entry: "
3906 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
3908 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot get environment entry's name.");
3913 if (is_unary_string(right_head
)) {
3914 char *right
= ctf_ast_concatenate_unary_strings(right_head
);
3917 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3919 "Unexpected unary expression for environment entry's value: "
3926 if (strcmp(left
, "tracer_name") == 0) {
3927 if (strncmp(right
, "lttng", 5) == 0) {
3928 BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: "
3929 "tracer-name=\"%s\"",
3931 ctx
->is_lttng
= true;
3935 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
,
3938 } else if (is_unary_unsigned(right_head
) || is_unary_signed(right_head
)) {
3941 if (is_unary_unsigned(right_head
)) {
3942 ret
= get_unary_unsigned(ctx
, right_head
, (uint64_t *) &v
);
3944 ret
= get_unary_signed(right_head
, &v
);
3947 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3949 "Unexpected unary expression for environment entry's value: "
3956 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
,
3959 _BT_COMP_LOGW_NODE(entry_node
,
3960 "Environment entry has unknown type: "
3977 static int set_trace_byte_order(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*trace_node
)
3982 struct ctf_node
*node
;
3983 struct bt_list_head
*decl_list
= &trace_node
->u
.trace
.declaration_list
;
3985 bt_list_for_each_entry (node
, decl_list
, siblings
) {
3986 if (node
->type
== NODE_CTF_EXPRESSION
) {
3987 struct ctf_node
*right_node
;
3989 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3991 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3996 if (strcmp(left
, "byte_order") == 0) {
3997 enum ctf_byte_order bo
;
3999 if (_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4000 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
4005 _SET(&set
, _TRACE_BYTE_ORDER_SET
);
4007 _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4008 bo
= byte_order_from_unary_expr(ctx
, right_node
);
4009 if (bo
== CTF_BYTE_ORDER_UNKNOWN
) {
4010 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4011 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4012 "expecting `le`, `be`, or `network`.");
4015 } else if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
4016 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4017 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4018 "cannot be set to `native` here.");
4023 ctx
->ctf_tc
->default_byte_order
= bo
;
4031 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4032 _BT_COMP_LOGE_APPEND_CAUSE_NODE(trace_node
,
4033 "Missing `byte_order` attribute in trace (`trace` block).");
4045 static int visit_clock_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
4046 struct ctf_clock_class
*clock
, int *set
, int64_t *offset_seconds
,
4047 uint64_t *offset_cycles
)
4052 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4053 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
4059 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
4061 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot concatenate unary strings.");
4066 if (strcmp(left
, "name") == 0) {
4069 if (_IS_SET(set
, _CLOCK_NAME_SET
)) {
4070 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "name", "clock class");
4075 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4077 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4078 entry_node
, "Unexpected unary expression for clock class's `name` attribute.");
4083 g_string_assign(clock
->name
, right
);
4085 _SET(set
, _CLOCK_NAME_SET
);
4086 } else if (strcmp(left
, "uuid") == 0) {
4089 if (_IS_SET(set
, _CLOCK_UUID_SET
)) {
4090 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "uuid", "clock class");
4095 ret
= get_unary_uuid(ctx
, &entry_node
->u
.ctf_expression
.right
, uuid
);
4097 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Invalid clock class's `uuid` attribute.");
4101 clock
->has_uuid
= true;
4102 bt_uuid_copy(clock
->uuid
, uuid
);
4103 _SET(set
, _CLOCK_UUID_SET
);
4104 } else if (strcmp(left
, "description") == 0) {
4107 if (_IS_SET(set
, _CLOCK_DESCRIPTION_SET
)) {
4108 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "description", "clock class");
4113 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4115 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4117 "Unexpected unary expression for clock class's `description` attribute.");
4122 g_string_assign(clock
->description
, right
);
4124 _SET(set
, _CLOCK_DESCRIPTION_SET
);
4125 } else if (strcmp(left
, "freq") == 0) {
4126 uint64_t freq
= UINT64_C(-1);
4128 if (_IS_SET(set
, _CLOCK_FREQ_SET
)) {
4129 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "freq", "clock class");
4134 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &freq
);
4136 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4137 entry_node
, "Unexpected unary expression for clock class's `freq` attribute.");
4142 if (freq
== UINT64_C(-1) || freq
== 0) {
4143 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4144 "Invalid clock class frequency: freq=%" PRIu64
, freq
);
4149 clock
->frequency
= freq
;
4150 _SET(set
, _CLOCK_FREQ_SET
);
4151 } else if (strcmp(left
, "precision") == 0) {
4154 if (_IS_SET(set
, _CLOCK_PRECISION_SET
)) {
4155 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "precision", "clock class");
4160 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &precision
);
4162 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4163 entry_node
, "Unexpected unary expression for clock class's `precision` attribute.");
4168 clock
->precision
= precision
;
4169 _SET(set
, _CLOCK_PRECISION_SET
);
4170 } else if (strcmp(left
, "offset_s") == 0) {
4171 if (_IS_SET(set
, _CLOCK_OFFSET_S_SET
)) {
4172 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset_s", "clock class");
4177 ret
= get_unary_signed(&entry_node
->u
.ctf_expression
.right
, offset_seconds
);
4179 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4180 entry_node
, "Unexpected unary expression for clock class's `offset_s` attribute.");
4185 _SET(set
, _CLOCK_OFFSET_S_SET
);
4186 } else if (strcmp(left
, "offset") == 0) {
4187 if (_IS_SET(set
, _CLOCK_OFFSET_SET
)) {
4188 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset", "clock class");
4193 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, offset_cycles
);
4195 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4196 entry_node
, "Unexpected unary expression for clock class's `offset` attribute.");
4201 _SET(set
, _CLOCK_OFFSET_SET
);
4202 } else if (strcmp(left
, "absolute") == 0) {
4203 struct ctf_node
*right
;
4205 if (_IS_SET(set
, _CLOCK_ABSOLUTE_SET
)) {
4206 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "absolute", "clock class");
4212 _BT_LIST_FIRST_ENTRY(&entry_node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4213 ret
= get_boolean(ctx
, right
);
4215 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4216 entry_node
, "Unexpected unary expression for clock class's `absolute` attribute.");
4221 clock
->is_absolute
= ret
;
4222 _SET(set
, _CLOCK_ABSOLUTE_SET
);
4224 _BT_COMP_LOGW_NODE(entry_node
, "Unknown attribute in clock class: attr-name=\"%s\"", left
);
4236 static inline uint64_t cycles_from_ns(uint64_t frequency
, uint64_t ns
)
4241 if (frequency
== UINT64_C(1000000000)) {
4244 cycles
= (uint64_t) (((double) ns
* (double) frequency
) / 1e9
);
4250 static void calibrate_clock_class_offsets(int64_t *offset_seconds
, uint64_t *offset_cycles
,
4253 if (*offset_cycles
>= freq
) {
4254 const uint64_t s_in_offset_cycles
= *offset_cycles
/ freq
;
4256 *offset_seconds
+= (int64_t) s_in_offset_cycles
;
4257 *offset_cycles
-= (s_in_offset_cycles
* freq
);
4261 static void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir
*ctx
,
4262 struct ctf_clock_class
*clock
)
4264 if (ctx
->decoder_config
.force_clock_class_origin_unix_epoch
) {
4265 clock
->is_absolute
= true;
4271 static void apply_clock_class_offset(struct ctf_visitor_generate_ir
*ctx
,
4272 struct ctf_clock_class
*clock
)
4275 int64_t offset_s_to_apply
= ctx
->decoder_config
.clock_class_offset_s
;
4276 uint64_t offset_ns_to_apply
;
4277 int64_t cur_offset_s
;
4278 uint64_t cur_offset_cycles
;
4280 if (ctx
->decoder_config
.clock_class_offset_s
== 0 &&
4281 ctx
->decoder_config
.clock_class_offset_ns
== 0) {
4285 /* Transfer nanoseconds to seconds as much as possible */
4286 if (ctx
->decoder_config
.clock_class_offset_ns
< 0) {
4287 const int64_t abs_ns
= -ctx
->decoder_config
.clock_class_offset_ns
;
4288 const int64_t abs_extra_s
= abs_ns
/ INT64_C(1000000000) + 1;
4289 const int64_t extra_s
= -abs_extra_s
;
4290 const int64_t offset_ns
=
4291 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4293 BT_ASSERT(offset_ns
> 0);
4294 offset_ns_to_apply
= (uint64_t) offset_ns
;
4295 offset_s_to_apply
+= extra_s
;
4297 const int64_t extra_s
= ctx
->decoder_config
.clock_class_offset_ns
/ INT64_C(1000000000);
4298 const int64_t offset_ns
=
4299 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4301 BT_ASSERT(offset_ns
>= 0);
4302 offset_ns_to_apply
= (uint64_t) offset_ns
;
4303 offset_s_to_apply
+= extra_s
;
4306 freq
= clock
->frequency
;
4307 cur_offset_s
= clock
->offset_seconds
;
4308 cur_offset_cycles
= clock
->offset_cycles
;
4311 cur_offset_s
+= offset_s_to_apply
;
4312 cur_offset_cycles
+= cycles_from_ns(freq
, offset_ns_to_apply
);
4315 * Recalibrate offsets because the part in cycles can be greater
4316 * than the frequency at this point.
4318 calibrate_clock_class_offsets(&cur_offset_s
, &cur_offset_cycles
, freq
);
4320 /* Set final offsets */
4321 clock
->offset_seconds
= cur_offset_s
;
4322 clock
->offset_cycles
= cur_offset_cycles
;
4328 static int visit_clock_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*clock_node
)
4332 struct ctf_clock_class
*clock
;
4333 struct ctf_node
*entry_node
;
4334 struct bt_list_head
*decl_list
= &clock_node
->u
.clock
.declaration_list
;
4335 const char *clock_class_name
;
4336 int64_t offset_seconds
= 0;
4337 uint64_t offset_cycles
= 0;
4340 if (clock_node
->visited
) {
4344 clock_node
->visited
= TRUE
;
4346 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4347 clock
= ctf_clock_class_create();
4349 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
, "Cannot create default clock class.");
4354 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
4355 ret
= visit_clock_decl_entry(ctx
, entry_node
, clock
, &set
, &offset_seconds
, &offset_cycles
);
4357 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot visit clock class's entry: ret=%d",
4363 if (!_IS_SET(&set
, _CLOCK_NAME_SET
)) {
4364 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
, "Missing `name` attribute in clock class.");
4369 clock_class_name
= clock
->name
->str
;
4370 BT_ASSERT(clock_class_name
);
4371 if (ctx
->is_lttng
&& strcmp(clock_class_name
, "monotonic") == 0) {
4373 * Old versions of LTTng forgot to set its clock class
4374 * as absolute, even if it is. This is important because
4375 * it's a condition to be able to sort messages
4376 * from different sources.
4378 clock
->is_absolute
= true;
4382 * Adjust offsets so that the part in cycles is less than the
4383 * frequency (move to the part in seconds).
4385 freq
= clock
->frequency
;
4386 calibrate_clock_class_offsets(&offset_seconds
, &offset_cycles
, freq
);
4387 BT_ASSERT(offset_cycles
< clock
->frequency
);
4388 clock
->offset_seconds
= offset_seconds
;
4389 clock
->offset_cycles
= offset_cycles
;
4390 apply_clock_class_offset(ctx
, clock
);
4391 apply_clock_class_is_absolute(ctx
, clock
);
4392 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock
);
4397 ctf_clock_class_destroy(clock
);
4403 static int visit_root_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*root_decl_node
)
4407 if (root_decl_node
->visited
) {
4411 root_decl_node
->visited
= TRUE
;
4413 switch (root_decl_node
->type
) {
4416 visit_field_class_def(ctx
, root_decl_node
->u
.field_class_def
.field_class_specifier_list
,
4417 &root_decl_node
->u
.field_class_def
.field_class_declarators
);
4419 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4420 "Cannot add field class found in root scope.");
4424 case NODE_TYPEALIAS
:
4425 ret
= visit_field_class_alias(ctx
, root_decl_node
->u
.field_class_alias
.target
,
4426 root_decl_node
->u
.field_class_alias
.alias
);
4428 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4429 "Cannot add field class alias found in root scope.");
4433 case NODE_TYPE_SPECIFIER_LIST
:
4435 struct ctf_field_class
*decl
= NULL
;
4438 * Just add the field class specifier to the root
4439 * declaration scope. Put local reference.
4441 ret
= visit_field_class_specifier_list(ctx
, root_decl_node
, &decl
);
4443 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4444 "Cannot visit root scope's field class: "
4451 ctf_field_class_destroy(decl
);
4456 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
, "Unexpected node type: node-type=%d",
4457 root_decl_node
->type
);
4466 struct ctf_visitor_generate_ir
*
4467 ctf_visitor_generate_ir_create(const struct ctf_metadata_decoder_config
*decoder_config
)
4469 struct ctf_visitor_generate_ir
*ctx
= NULL
;
4471 /* Create visitor's context */
4472 ctx
= ctx_create(decoder_config
);
4474 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
, decoder_config
->self_comp
,
4475 "Cannot create visitor's context.");
4489 void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir
*visitor
)
4491 ctx_destroy(visitor
);
4494 bt_trace_class
*ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4498 if (ctx
->trace_class
) {
4499 bt_trace_class_get_ref(ctx
->trace_class
);
4502 return ctx
->trace_class
;
4505 struct ctf_trace_class
*
4506 ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4509 BT_ASSERT_DBG(ctx
->ctf_tc
);
4513 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
4517 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
4519 switch (node
->type
) {
4522 struct ctf_node
*iter
;
4523 bool got_trace_decl
= false;
4526 * The first thing we need is the native byte order of
4527 * the trace block, because early class aliases can have
4528 * a `byte_order` attribute set to `native`. If we don't
4529 * have the native byte order yet, and we don't have any
4530 * trace block yet, then fail with EINCOMPLETE.
4532 if (ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
4533 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4534 if (got_trace_decl
) {
4535 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
4540 ret
= set_trace_byte_order(ctx
, iter
);
4542 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4543 "Cannot set trace's native byte order: "
4549 got_trace_decl
= true;
4552 if (!got_trace_decl
) {
4553 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
4559 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_LITTLE
||
4560 ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_BIG
);
4561 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4564 bt_list_for_each_entry (iter
, &node
->u
.root
.env
, siblings
) {
4565 ret
= visit_env(ctx
, iter
);
4567 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4569 "Cannot visit trace's environment (`env` block) entry: "
4576 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4579 * Visit clock blocks.
4581 bt_list_for_each_entry (iter
, &node
->u
.root
.clock
, siblings
) {
4582 ret
= visit_clock_decl(ctx
, iter
);
4584 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit clock class: ret=%d", ret
);
4589 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4592 * Visit root declarations next, as they can be used by any
4595 bt_list_for_each_entry (iter
, &node
->u
.root
.declaration_list
, siblings
) {
4596 ret
= visit_root_decl(ctx
, iter
);
4598 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit root entry: ret=%d", ret
);
4603 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4605 /* Callsite blocks are not supported */
4606 bt_list_for_each_entry (iter
, &node
->u
.root
.callsite
, siblings
) {
4607 _BT_COMP_LOGW_NODE(iter
, "\"callsite\" blocks are not supported as of this version.");
4610 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4613 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4614 ret
= visit_trace_decl(ctx
, iter
);
4616 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4617 "Cannot visit trace (`trace` block): "
4624 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4627 bt_list_for_each_entry (iter
, &node
->u
.root
.stream
, siblings
) {
4628 ret
= visit_stream_decl(ctx
, iter
);
4630 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit stream class: ret=%d", ret
);
4635 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4638 bt_list_for_each_entry (iter
, &node
->u
.root
.event
, siblings
) {
4639 ret
= visit_event_decl(ctx
, iter
);
4641 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit event class: ret=%d", ret
);
4646 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4650 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected node type: node-type=%d", node
->type
);
4655 /* Update default clock classes */
4656 ret
= ctf_trace_class_update_default_clock_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4662 /* Update trace class meanings */
4663 ret
= ctf_trace_class_update_meanings(ctx
->ctf_tc
);
4669 /* Update stream class configuration */
4670 ret
= ctf_trace_class_update_stream_class_config(ctx
->ctf_tc
);
4676 /* Update text arrays and sequences */
4677 ret
= ctf_trace_class_update_text_array_sequence(ctx
->ctf_tc
);
4683 /* Update structure/array/sequence alignments */
4684 ret
= ctf_trace_class_update_alignments(ctx
->ctf_tc
);
4690 /* Resolve sequence lengths and variant tags */
4691 ret
= ctf_trace_class_resolve_field_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4697 if (ctx
->trace_class
) {
4699 * Update "in IR" for field classes.
4701 * If we have no IR trace class, then we'll have no way
4702 * to create IR fields anyway, so we leave all the
4703 * `in_ir` members false.
4705 ret
= ctf_trace_class_update_in_ir(ctx
->ctf_tc
);
4712 /* Update saved value indexes */
4713 ret
= ctf_trace_class_update_value_storing_indexes(ctx
->ctf_tc
);
4719 /* Validate what we have so far */
4720 ret
= ctf_trace_class_validate(ctx
->ctf_tc
, &ctx
->log_cfg
);
4727 * If there are fields which are not related to the CTF format
4728 * itself in the packet header and in event header field
4729 * classes, warn about it because they are never translated.
4731 ctf_trace_class_warn_meaningless_header_fields(ctx
->ctf_tc
, &ctx
->log_cfg
);
4733 if (ctx
->trace_class
) {
4734 /* Copy new CTF metadata -> new IR metadata */
4735 ret
= ctf_trace_class_translate(ctx
->log_cfg
.self_comp
, ctx
->trace_class
, ctx
->ctf_tc
);