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).
13 #include "logging.hpp"
15 #include "common/assert.h"
16 #include "common/common.h"
17 #include "common/uuid.h"
18 #include "compat/endian.h" /* IWYU pragma: keep */
19 #include "cpp-common/bt2c/logging.hpp"
22 #include "ctf-meta-visitors.hpp"
24 /* Bit value (left shift) */
25 #define _BV(_val) (1 << (_val))
27 /* Bit is set in a set of bits */
28 #define _IS_SET(_set, _mask) (*(_set) & (_mask))
30 /* Set bit in a set of bits */
31 #define _SET(_set, _mask) (*(_set) |= (_mask))
33 /* Try to push scope, or go to the `error` label */
34 #define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
36 ret = ctx_push_scope(ctx); \
38 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger, "Cannot push scope."); \
43 /* Bits for verifying existing attributes in various declarations */
46 _CLOCK_NAME_SET
= _BV(0),
47 _CLOCK_UUID_SET
= _BV(1),
48 _CLOCK_FREQ_SET
= _BV(2),
49 _CLOCK_PRECISION_SET
= _BV(3),
50 _CLOCK_OFFSET_S_SET
= _BV(4),
51 _CLOCK_OFFSET_SET
= _BV(5),
52 _CLOCK_ABSOLUTE_SET
= _BV(6),
53 _CLOCK_DESCRIPTION_SET
= _BV(7),
58 _INTEGER_ALIGN_SET
= _BV(0),
59 _INTEGER_SIZE_SET
= _BV(1),
60 _INTEGER_BASE_SET
= _BV(2),
61 _INTEGER_ENCODING_SET
= _BV(3),
62 _INTEGER_BYTE_ORDER_SET
= _BV(4),
63 _INTEGER_SIGNED_SET
= _BV(5),
64 _INTEGER_MAP_SET
= _BV(6),
69 _FLOAT_ALIGN_SET
= _BV(0),
70 _FLOAT_MANT_DIG_SET
= _BV(1),
71 _FLOAT_EXP_DIG_SET
= _BV(2),
72 _FLOAT_BYTE_ORDER_SET
= _BV(3),
77 _STRING_ENCODING_SET
= _BV(0),
82 _TRACE_MINOR_SET
= _BV(0),
83 _TRACE_MAJOR_SET
= _BV(1),
84 _TRACE_BYTE_ORDER_SET
= _BV(2),
85 _TRACE_UUID_SET
= _BV(3),
86 _TRACE_PACKET_HEADER_SET
= _BV(4),
91 _STREAM_ID_SET
= _BV(0),
92 _STREAM_PACKET_CONTEXT_SET
= _BV(1),
93 _STREAM_EVENT_HEADER_SET
= _BV(2),
94 _STREAM_EVENT_CONTEXT_SET
= _BV(3),
99 _EVENT_NAME_SET
= _BV(0),
100 _EVENT_ID_SET
= _BV(1),
101 _EVENT_MODEL_EMF_URI_SET
= _BV(2),
102 _EVENT_STREAM_ID_SET
= _BV(3),
103 _EVENT_LOG_LEVEL_SET
= _BV(4),
104 _EVENT_CONTEXT_SET
= _BV(5),
105 _EVENT_FIELDS_SET
= _BV(6),
114 LOG_LEVEL_WARNING
= 4,
115 LOG_LEVEL_NOTICE
= 5,
117 LOG_LEVEL_DEBUG_SYSTEM
= 7,
118 LOG_LEVEL_DEBUG_PROGRAM
= 8,
119 LOG_LEVEL_DEBUG_PROCESS
= 9,
120 LOG_LEVEL_DEBUG_MODULE
= 10,
121 LOG_LEVEL_DEBUG_UNIT
= 11,
122 LOG_LEVEL_DEBUG_FUNCTION
= 12,
123 LOG_LEVEL_DEBUG_LINE
= 13,
124 LOG_LEVEL_DEBUG
= 14,
128 /* Prefixes of class aliases */
129 #define _PREFIX_ALIAS 'a'
130 #define _PREFIX_ENUM 'e'
131 #define _PREFIX_STRUCT 's'
132 #define _PREFIX_VARIANT 'v'
134 /* First entry in a BT list */
135 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) bt_list_entry((_ptr)->next, _class, _member)
137 #define _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \
138 _BT_CPPLOGE_APPEND_CAUSE_LINENO(ctx->logger, (_node)->lineno, \
139 "Duplicate attribute in {}: attr-name=\"{}\"", _entity, _attr)
141 #define _BT_CPPLOGE_NODE(_node, _msg, args...) \
142 _BT_CPPLOGE_LINENO(ctx->logger, (_node)->lineno, _msg, ##args)
144 #define _BT_CPPLOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
145 _BT_CPPLOGE_APPEND_CAUSE_LINENO(ctx->logger, (_node)->lineno, _msg, ##args)
147 #define _BT_CPPLOGW_NODE(_node, _msg, args...) \
148 _BT_CPPLOGW_LINENO(ctx->logger, (_node)->lineno, _msg, ##args)
150 #define _BT_CPPLOGT_NODE(_node, _msg, args...) \
151 _BT_CPPLOGT_LINENO(ctx->logger, (_node)->lineno, _msg, ##args)
154 * Declaration scope of a visitor context. This represents a TSDL
155 * lexical scope, so that aliases and named structures, variants,
156 * and enumerations may be registered and looked up hierarchically.
158 struct ctx_decl_scope
161 * Alias name to field class.
163 * GQuark -> struct ctf_field_class * (owned by this)
165 GHashTable
*decl_map
;
167 /* Parent scope; NULL if this is the root declaration scope */
168 struct ctx_decl_scope
*parent_scope
;
172 * Visitor context (private).
174 struct ctf_visitor_generate_ir
176 explicit ctf_visitor_generate_ir(ctf_metadata_decoder_config decoderConfig
,
177 bt2c::Logger loggerParam
) :
178 decoder_config
{std::move(decoderConfig
)},
179 logger
{std::move(loggerParam
)}
183 /* Trace IR trace class being filled (owned by this) */
184 bt_trace_class
*trace_class
= nullptr;
186 /* CTF meta trace being filled (owned by this) */
187 struct ctf_trace_class
*ctf_tc
= nullptr;
189 /* Current declaration scope (top of the stack) (owned by this) */
190 struct ctx_decl_scope
*current_scope
= nullptr;
192 /* True if trace declaration is visited */
193 bool is_trace_visited
= false;
195 /* True if this is an LTTng trace */
196 bool is_lttng
= false;
198 /* Config passed by the user */
199 struct ctf_metadata_decoder_config decoder_config
;
207 struct ctf_visitor_generate_ir
;
210 * Creates a new declaration scope.
212 * @param par_scope Parent scope (NULL if creating a root scope)
213 * @returns New declaration scope, or NULL on error
215 static struct ctx_decl_scope
*ctx_decl_scope_create(struct ctf_visitor_generate_ir
*ctx
,
216 struct ctx_decl_scope
*par_scope
)
218 struct ctx_decl_scope
*scope
;
220 scope
= g_new(struct ctx_decl_scope
, 1);
222 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Failed to allocate one declaration scope.");
226 scope
->decl_map
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
,
227 (GDestroyNotify
) ctf_field_class_destroy
);
228 scope
->parent_scope
= par_scope
;
235 * Destroys a declaration scope.
237 * This function does not destroy the parent scope.
239 * @param scope Scope to destroy
241 static void ctx_decl_scope_destroy(struct ctx_decl_scope
*scope
)
247 g_hash_table_destroy(scope
->decl_map
);
255 * Returns the GQuark of a prefixed alias.
257 * @param prefix Prefix character
259 * @returns Associated GQuark, or 0 on error
261 static GQuark
get_prefixed_named_quark(char prefix
, const char *name
)
264 std::string prname
= std::string
{prefix
} + name
;
265 return g_quark_from_string(prname
.c_str());
269 * Looks up a prefixed class alias within a declaration scope.
271 * @param scope Declaration scope
272 * @param prefix Prefix character
273 * @param name Alias name
274 * @param levels Number of levels to dig into (-1 means infinite)
275 * @param copy True to return a copy
276 * @returns Declaration (owned by caller if \p copy is true),
277 * or NULL if not found
279 static struct ctf_field_class
*ctx_decl_scope_lookup_prefix_alias(struct ctx_decl_scope
*scope
,
280 char prefix
, const char *name
,
281 int levels
, bool copy
)
285 struct ctf_field_class
*decl
= NULL
;
286 struct ctx_decl_scope
*cur_scope
= scope
;
290 qname
= get_prefixed_named_quark(prefix
, name
);
299 while (cur_scope
&& cur_levels
< levels
) {
300 decl
= (ctf_field_class
*) g_hash_table_lookup(cur_scope
->decl_map
,
301 (gconstpointer
) GUINT_TO_POINTER(qname
));
303 /* Caller's reference */
305 decl
= ctf_field_class_copy(decl
);
312 cur_scope
= cur_scope
->parent_scope
;
321 * Looks up a class alias within a declaration scope.
323 * @param scope Declaration scope
324 * @param name Alias name
325 * @param levels Number of levels to dig into (-1 means infinite)
326 * @param copy True to return a copy
327 * @returns Declaration (owned by caller if \p copy is true),
328 * or NULL if not found
330 static struct ctf_field_class
*ctx_decl_scope_lookup_alias(struct ctx_decl_scope
*scope
,
331 const char *name
, int levels
, bool copy
)
333 return ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ALIAS
, name
, levels
, copy
);
337 * Looks up an enumeration within a declaration scope.
339 * @param scope Declaration scope
340 * @param name Enumeration name
341 * @param levels Number of levels to dig into (-1 means infinite)
342 * @param copy True to return a copy
343 * @returns Declaration (owned by caller if \p copy is true),
344 * or NULL if not found
346 static struct ctf_field_class_enum
*
347 ctx_decl_scope_lookup_enum(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
349 return ctf_field_class_as_enum(
350 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ENUM
, name
, levels
, copy
));
354 * Looks up a structure within a declaration scope.
356 * @param scope Declaration scope
357 * @param name Structure name
358 * @param levels Number of levels to dig into (-1 means infinite)
359 * @param copy True to return a copy
360 * @returns Declaration (owned by caller if \p copy is true),
361 * or NULL if not found
363 static struct ctf_field_class_struct
*
364 ctx_decl_scope_lookup_struct(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
366 return ctf_field_class_as_struct(
367 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_STRUCT
, name
, levels
, copy
));
371 * Looks up a variant within a declaration scope.
373 * @param scope Declaration scope
374 * @param name Variant name
375 * @param levels Number of levels to dig into (-1 means infinite)
376 * @param copy True to return a copy
377 * @returns Declaration (owned by caller if \p copy is true),
378 * or NULL if not found
380 static struct ctf_field_class_variant
*
381 ctx_decl_scope_lookup_variant(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
383 return ctf_field_class_as_variant(
384 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_VARIANT
, name
, levels
, copy
));
388 * Registers a prefixed class alias within a declaration scope.
390 * @param scope Declaration scope
391 * @param prefix Prefix character
392 * @param name Alias name (non-NULL)
393 * @param decl Field class to register (copied)
394 * @returns 0 if registration went okay, negative value otherwise
396 static int ctx_decl_scope_register_prefix_alias(struct ctx_decl_scope
*scope
, char prefix
,
397 const char *name
, struct ctf_field_class
*decl
)
405 qname
= get_prefixed_named_quark(prefix
, name
);
411 /* Make sure alias does not exist in local scope */
412 if (ctx_decl_scope_lookup_prefix_alias(scope
, prefix
, name
, 1, false)) {
417 decl
= ctf_field_class_copy(decl
);
419 g_hash_table_insert(scope
->decl_map
, GUINT_TO_POINTER(qname
), decl
);
426 * Registers a class alias within a declaration scope.
428 * @param scope Declaration scope
429 * @param name Alias name (non-NULL)
430 * @param decl Field class to register (copied)
431 * @returns 0 if registration went okay, negative value otherwise
433 static int ctx_decl_scope_register_alias(struct ctx_decl_scope
*scope
, const char *name
,
434 struct ctf_field_class
*decl
)
436 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ALIAS
, name
, decl
);
440 * Registers an enumeration declaration within a declaration scope.
442 * @param scope Declaration scope
443 * @param name Enumeration name (non-NULL)
444 * @param decl Enumeration field class to register (copied)
445 * @returns 0 if registration went okay, negative value otherwise
447 static int ctx_decl_scope_register_enum(struct ctx_decl_scope
*scope
, const char *name
,
448 struct ctf_field_class_enum
*decl
)
450 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ENUM
, name
, &decl
->base
.base
.base
);
454 * Registers a structure declaration within a declaration scope.
456 * @param scope Declaration scope
457 * @param name Structure name (non-NULL)
458 * @param decl Structure field class to register (copied)
459 * @returns 0 if registration went okay, negative value otherwise
461 static int ctx_decl_scope_register_struct(struct ctx_decl_scope
*scope
, const char *name
,
462 struct ctf_field_class_struct
*decl
)
464 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_STRUCT
, name
, &decl
->base
);
468 * Registers a variant declaration within a declaration scope.
470 * @param scope Declaration scope
471 * @param name Variant name (non-NULL)
472 * @param decl Variant field class to register
473 * @returns 0 if registration went okay, negative value otherwise
475 static int ctx_decl_scope_register_variant(struct ctx_decl_scope
*scope
, const char *name
,
476 struct ctf_field_class_variant
*decl
)
478 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_VARIANT
, name
, &decl
->base
);
482 * Destroys a visitor context.
484 * @param ctx Visitor context to destroy
486 static void ctx_destroy(struct ctf_visitor_generate_ir
*ctx
)
488 struct ctx_decl_scope
*scope
;
494 scope
= ctx
->current_scope
;
497 * Destroy all scopes, from current one to the root scope.
500 struct ctx_decl_scope
*parent_scope
= scope
->parent_scope
;
502 ctx_decl_scope_destroy(scope
);
503 scope
= parent_scope
;
506 bt_trace_class_put_ref(ctx
->trace_class
);
509 ctf_trace_class_destroy(ctx
->ctf_tc
);
519 * Creates a new visitor context.
521 * @param trace Associated trace
522 * @returns New visitor context, or NULL on error
524 static struct ctf_visitor_generate_ir
*
525 ctx_create(const struct ctf_metadata_decoder_config
*decoder_config
, const bt2c::Logger
& logger
)
527 BT_ASSERT(decoder_config
);
529 ctf_visitor_generate_ir
*ctx
= new ctf_visitor_generate_ir
{*decoder_config
, logger
};
531 if (decoder_config
->self_comp
) {
532 ctx
->trace_class
= bt_trace_class_create(decoder_config
->self_comp
);
533 if (!ctx
->trace_class
) {
534 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Cannot create empty trace class.");
539 ctx
->ctf_tc
= ctf_trace_class_create();
541 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Cannot create CTF trace class.");
545 /* Root declaration scope */
546 ctx
->current_scope
= ctx_decl_scope_create(ctx
, NULL
);
547 if (!ctx
->current_scope
) {
548 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Cannot create declaration scope.");
563 * Pushes a new declaration scope on top of a visitor context's
564 * declaration scope stack.
566 * @param ctx Visitor context
567 * @returns 0 on success, or a negative value on error
569 static int ctx_push_scope(struct ctf_visitor_generate_ir
*ctx
)
572 struct ctx_decl_scope
*new_scope
;
575 new_scope
= ctx_decl_scope_create(ctx
, ctx
->current_scope
);
577 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Cannot create declaration scope.");
582 ctx
->current_scope
= new_scope
;
588 static void ctx_pop_scope(struct ctf_visitor_generate_ir
*ctx
)
590 struct ctx_decl_scope
*parent_scope
= NULL
;
594 if (!ctx
->current_scope
) {
598 parent_scope
= ctx
->current_scope
->parent_scope
;
599 ctx_decl_scope_destroy(ctx
->current_scope
);
600 ctx
->current_scope
= parent_scope
;
606 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
607 struct ctf_node
*ts_list
,
608 struct ctf_field_class
**decl
);
610 static int is_unary_string(struct bt_list_head
*head
)
613 struct ctf_node
*node
;
615 bt_list_for_each_entry (node
, head
, siblings
) {
616 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
620 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
628 static const char *get_map_clock_name_value(struct bt_list_head
*head
)
631 struct ctf_node
*node
;
632 const char *name
= NULL
;
634 bt_list_for_each_entry (node
, head
, siblings
) {
636 int uexpr_type
= node
->u
.unary_expression
.type
;
637 int uexpr_link
= node
->u
.unary_expression
.link
;
638 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_STRING
||
639 !((uexpr_link
!= UNARY_LINK_UNKNOWN
) ^ (i
== 0));
644 /* Needs to be chained with . */
645 switch (node
->u
.unary_expression
.link
) {
648 case UNARY_ARROWLINK
:
649 case UNARY_DOTDOTDOT
:
655 src_string
= node
->u
.unary_expression
.u
.string
;
659 if (strcmp("clock", src_string
)) {
667 if (strcmp("value", src_string
)) {
672 /* Extra identifier, unknown */
685 static int is_unary_unsigned(struct bt_list_head
*head
)
688 struct ctf_node
*node
;
690 bt_list_for_each_entry (node
, head
, siblings
) {
691 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
695 if (node
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
703 static int get_unary_unsigned(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
708 struct ctf_node
*node
;
712 if (bt_list_empty(head
)) {
717 bt_list_for_each_entry (node
, head
, siblings
) {
718 int uexpr_type
= node
->u
.unary_expression
.type
;
719 int uexpr_link
= node
->u
.unary_expression
.link
;
720 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_UNSIGNED_CONSTANT
||
721 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
723 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Invalid constant unsigned integer.");
728 *value
= node
->u
.unary_expression
.u
.unsigned_constant
;
736 static int is_unary_signed(struct bt_list_head
*head
)
739 struct ctf_node
*node
;
741 bt_list_for_each_entry (node
, head
, siblings
) {
742 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
746 if (node
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
) {
754 static int get_unary_signed(struct bt_list_head
*head
, int64_t *value
)
758 struct ctf_node
*node
;
760 bt_list_for_each_entry (node
, head
, siblings
) {
761 int uexpr_type
= node
->u
.unary_expression
.type
;
762 int uexpr_link
= node
->u
.unary_expression
.link
;
763 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
764 (uexpr_type
!= UNARY_UNSIGNED_CONSTANT
&& uexpr_type
!= UNARY_SIGNED_CONSTANT
) ||
765 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
771 switch (uexpr_type
) {
772 case UNARY_UNSIGNED_CONSTANT
:
773 *value
= (int64_t) node
->u
.unary_expression
.u
.unsigned_constant
;
775 case UNARY_SIGNED_CONSTANT
:
776 *value
= node
->u
.unary_expression
.u
.signed_constant
;
790 static int get_unary_uuid(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
793 return ctf_ast_get_unary_uuid(head
, uuid
, ctx
->logger
);
796 static int get_boolean(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*unary_expr
)
800 if (unary_expr
->type
!= NODE_UNARY_EXPRESSION
) {
801 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr
, "Expecting unary expression: node-type={}",
807 switch (unary_expr
->u
.unary_expression
.type
) {
808 case UNARY_UNSIGNED_CONSTANT
:
809 ret
= (unary_expr
->u
.unary_expression
.u
.unsigned_constant
!= 0);
811 case UNARY_SIGNED_CONSTANT
:
812 ret
= (unary_expr
->u
.unary_expression
.u
.signed_constant
!= 0);
816 const char *str
= unary_expr
->u
.unary_expression
.u
.string
;
818 if (strcmp(str
, "true") == 0 || strcmp(str
, "TRUE") == 0) {
820 } else if (strcmp(str
, "false") == 0 || strcmp(str
, "FALSE") == 0) {
823 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr
, "Unexpected boolean value: value=\"{}\"",
831 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr
, "Unexpected unary expression type: node-type={}",
832 unary_expr
->u
.unary_expression
.type
);
841 static enum ctf_byte_order
byte_order_from_unary_expr(struct ctf_visitor_generate_ir
*ctx
,
842 struct ctf_node
*unary_expr
)
845 enum ctf_byte_order bo
= CTF_BYTE_ORDER_UNKNOWN
;
847 if (unary_expr
->u
.unary_expression
.type
!= UNARY_STRING
) {
848 _BT_CPPLOGE_APPEND_CAUSE_NODE(
849 unary_expr
, "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
853 str
= unary_expr
->u
.unary_expression
.u
.string
;
855 if (strcmp(str
, "be") == 0 || strcmp(str
, "network") == 0) {
856 bo
= CTF_BYTE_ORDER_BIG
;
857 } else if (strcmp(str
, "le") == 0) {
858 bo
= CTF_BYTE_ORDER_LITTLE
;
859 } else if (strcmp(str
, "native") == 0) {
860 bo
= CTF_BYTE_ORDER_DEFAULT
;
862 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr
,
863 "Unexpected \"byte_order\" attribute value: "
864 "expecting `be`, `le`, `network`, or `native`: value=\"{}\"",
873 static enum ctf_byte_order
get_real_byte_order(struct ctf_visitor_generate_ir
*ctx
,
874 struct ctf_node
*uexpr
)
876 enum ctf_byte_order bo
= byte_order_from_unary_expr(ctx
, uexpr
);
878 if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
879 bo
= ctx
->ctf_tc
->default_byte_order
;
885 static int is_align_valid(uint64_t align
)
887 return (align
!= 0) && !(align
& (align
- UINT64_C(1)));
890 static int get_class_specifier_name(struct ctf_visitor_generate_ir
*ctx
,
891 struct ctf_node
*cls_specifier
, GString
*str
)
895 if (cls_specifier
->type
!= NODE_TYPE_SPECIFIER
) {
896 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier
, "Unexpected node type: node-type={}",
897 cls_specifier
->type
);
902 switch (cls_specifier
->u
.field_class_specifier
.type
) {
904 g_string_append(str
, "void");
907 g_string_append(str
, "char");
910 g_string_append(str
, "short");
913 g_string_append(str
, "int");
916 g_string_append(str
, "long");
919 g_string_append(str
, "float");
921 case TYPESPEC_DOUBLE
:
922 g_string_append(str
, "double");
924 case TYPESPEC_SIGNED
:
925 g_string_append(str
, "signed");
927 case TYPESPEC_UNSIGNED
:
928 g_string_append(str
, "unsigned");
931 g_string_append(str
, "bool");
933 case TYPESPEC_COMPLEX
:
934 g_string_append(str
, "_Complex");
936 case TYPESPEC_IMAGINARY
:
937 g_string_append(str
, "_Imaginary");
940 g_string_append(str
, "const");
942 case TYPESPEC_ID_TYPE
:
943 if (cls_specifier
->u
.field_class_specifier
.id_type
) {
944 g_string_append(str
, cls_specifier
->u
.field_class_specifier
.id_type
);
947 case TYPESPEC_STRUCT
:
949 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
951 if (!node
->u
._struct
.name
) {
952 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty structure field class name.");
957 g_string_append(str
, "struct ");
958 g_string_append(str
, node
->u
._struct
.name
);
961 case TYPESPEC_VARIANT
:
963 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
965 if (!node
->u
.variant
.name
) {
966 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty variant field class name.");
971 g_string_append(str
, "variant ");
972 g_string_append(str
, node
->u
.variant
.name
);
977 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
979 if (!node
->u
._enum
.enum_id
) {
980 _BT_CPPLOGE_APPEND_CAUSE_NODE(
981 node
, "Unexpected empty enumeration field class (`enum`) name.");
986 g_string_append(str
, "enum ");
987 g_string_append(str
, node
->u
._enum
.enum_id
);
990 case TYPESPEC_FLOATING_POINT
:
991 case TYPESPEC_INTEGER
:
992 case TYPESPEC_STRING
:
994 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier
->u
.field_class_specifier
.node
,
995 "Unexpected field class specifier type: {}",
996 cls_specifier
->u
.field_class_specifier
.type
);
1005 static int get_class_specifier_list_name(struct ctf_visitor_generate_ir
*ctx
,
1006 struct ctf_node
*cls_specifier_list
, GString
*str
)
1009 struct ctf_node
*iter
;
1010 int alias_item_nr
= 0;
1011 struct bt_list_head
*head
= &cls_specifier_list
->u
.field_class_specifier_list
.head
;
1013 bt_list_for_each_entry (iter
, head
, siblings
) {
1014 if (alias_item_nr
!= 0) {
1015 g_string_append(str
, " ");
1019 ret
= get_class_specifier_name(ctx
, iter
, str
);
1029 static GQuark
create_class_alias_identifier(struct ctf_visitor_generate_ir
*ctx
,
1030 struct ctf_node
*cls_specifier_list
,
1031 struct ctf_node
*node_field_class_declarator
)
1037 struct ctf_node
*iter
;
1038 struct bt_list_head
*pointers
= &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1040 str
= g_string_new("");
1041 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
1043 g_string_free(str
, TRUE
);
1047 bt_list_for_each_entry (iter
, pointers
, siblings
) {
1048 g_string_append(str
, " *");
1050 if (iter
->u
.pointer
.const_qualifier
) {
1051 g_string_append(str
, " const");
1055 str_c
= g_string_free(str
, FALSE
);
1056 qalias
= g_quark_from_string(str_c
);
1063 static int visit_field_class_declarator(struct ctf_visitor_generate_ir
*ctx
,
1064 struct ctf_node
*cls_specifier_list
, GQuark
*field_name
,
1065 struct ctf_node
*node_field_class_declarator
,
1066 struct ctf_field_class
**field_decl
,
1067 struct ctf_field_class
*nested_decl
)
1070 * During this whole function, nested_decl is always OURS,
1071 * whereas field_decl is an output which we create, but
1072 * belongs to the caller (it is moved).
1077 /* Validate field class declarator node */
1078 if (node_field_class_declarator
) {
1079 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_UNKNOWN
) {
1080 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1081 node_field_class_declarator
, "Unexpected field class declarator type: type={}",
1082 node_field_class_declarator
->u
.field_class_declarator
.type
);
1087 /* TODO: GCC bitfields not supported yet */
1088 if (node_field_class_declarator
->u
.field_class_declarator
.bitfield_len
!= NULL
) {
1089 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1090 "GCC bitfields are not supported as of this version.");
1096 /* Find the right nested declaration if not provided */
1098 if (node_field_class_declarator
&&
1099 !bt_list_empty(&node_field_class_declarator
->u
.field_class_declarator
.pointers
)) {
1103 * If we have a pointer declarator, it HAS to
1104 * be present in the field class aliases (else
1108 create_class_alias_identifier(ctx
, cls_specifier_list
, node_field_class_declarator
);
1109 nested_decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, g_quark_to_string(qalias
),
1112 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1113 "Cannot find class alias: name=\"{}\"",
1114 g_quark_to_string(qalias
));
1119 if (nested_decl
->type
== CTF_FIELD_CLASS_TYPE_INT
) {
1120 /* Pointer: force integer's base to 16 */
1121 struct ctf_field_class_int
*int_fc
= ctf_field_class_as_int(nested_decl
);
1123 int_fc
->disp_base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
1126 ret
= visit_field_class_specifier_list(ctx
, cls_specifier_list
, &nested_decl
);
1128 BT_ASSERT(!nested_decl
);
1134 BT_ASSERT(nested_decl
);
1136 if (!node_field_class_declarator
) {
1137 *field_decl
= nested_decl
;
1142 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_ID
) {
1143 if (node_field_class_declarator
->u
.field_class_declarator
.u
.id
) {
1144 const char *id
= node_field_class_declarator
->u
.field_class_declarator
.u
.id
;
1146 *field_name
= g_quark_from_string(id
);
1151 *field_decl
= nested_decl
;
1155 struct ctf_node
*first
;
1156 struct ctf_field_class
*decl
= NULL
;
1157 struct ctf_field_class
*outer_field_decl
= NULL
;
1158 struct bt_list_head
*length
=
1159 &node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.length
;
1161 /* Create array/sequence, pass nested_decl as child */
1162 if (bt_list_empty(length
)) {
1163 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1164 "Expecting length field reference or value.");
1169 first
= _BT_LIST_FIRST_ENTRY(length
, struct ctf_node
, siblings
);
1170 if (first
->type
!= NODE_UNARY_EXPRESSION
) {
1171 _BT_CPPLOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type={}", first
->type
);
1176 switch (first
->u
.unary_expression
.type
) {
1177 case UNARY_UNSIGNED_CONSTANT
:
1179 struct ctf_field_class_array
*array_decl
= NULL
;
1181 array_decl
= ctf_field_class_array_create();
1182 BT_ASSERT(array_decl
);
1183 array_decl
->length
= first
->u
.unary_expression
.u
.unsigned_constant
;
1184 array_decl
->base
.elem_fc
= nested_decl
;
1186 decl
= &array_decl
->base
.base
;
1191 /* Lookup unsigned integer definition, create seq. */
1192 struct ctf_field_class_sequence
*seq_decl
= NULL
;
1193 char *length_name
= ctf_ast_concatenate_unary_strings(length
);
1196 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1197 "Cannot concatenate unary strings.");
1202 if (strncmp(length_name
, "env.", 4) == 0) {
1203 /* This is, in fact, an array */
1204 const char *env_entry_name
= &length_name
[4];
1205 struct ctf_trace_class_env_entry
*env_entry
=
1206 ctf_trace_class_borrow_env_entry_by_name(ctx
->ctf_tc
, env_entry_name
);
1207 struct ctf_field_class_array
*array_decl
;
1210 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1211 "Cannot find environment entry: "
1218 if (env_entry
->type
!= CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
) {
1219 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1220 "Wrong environment entry type "
1221 "(expecting integer): "
1228 if (env_entry
->value
.i
< 0) {
1229 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1230 "Invalid, negative array length: "
1231 "env-entry-name=\"{}\", "
1233 env_entry_name
, env_entry
->value
.i
);
1238 array_decl
= ctf_field_class_array_create();
1239 BT_ASSERT(array_decl
);
1240 array_decl
->length
= (uint64_t) env_entry
->value
.i
;
1241 array_decl
->base
.elem_fc
= nested_decl
;
1243 decl
= &array_decl
->base
.base
;
1245 seq_decl
= ctf_field_class_sequence_create();
1246 BT_ASSERT(seq_decl
);
1247 seq_decl
->base
.elem_fc
= nested_decl
;
1249 g_string_assign(seq_decl
->length_ref
, length_name
);
1250 decl
= &seq_decl
->base
.base
;
1253 g_free(length_name
);
1261 BT_ASSERT(!nested_decl
);
1263 BT_ASSERT(!*field_decl
);
1266 * At this point, we found the next nested declaration.
1267 * We currently own this (and lost the ownership of
1268 * nested_decl in the meantime). Pass this next
1269 * nested declaration as the content of the outer
1270 * container, MOVING its ownership.
1272 ret
= visit_field_class_declarator(
1273 ctx
, cls_specifier_list
, field_name
,
1274 node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.field_class_declarator
,
1275 &outer_field_decl
, decl
);
1278 BT_ASSERT(!outer_field_decl
);
1283 BT_ASSERT(outer_field_decl
);
1284 *field_decl
= outer_field_decl
;
1285 outer_field_decl
= NULL
;
1288 BT_ASSERT(*field_decl
);
1292 ctf_field_class_destroy(*field_decl
);
1300 ctf_field_class_destroy(nested_decl
);
1305 static int visit_struct_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1306 struct ctf_field_class_struct
*struct_decl
,
1307 struct ctf_node
*cls_specifier_list
,
1308 struct bt_list_head
*field_class_declarators
)
1311 struct ctf_node
*iter
;
1312 struct ctf_field_class
*field_decl
= NULL
;
1314 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1317 const char *field_name
;
1319 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1322 BT_ASSERT(!field_decl
);
1323 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1324 "Cannot visit field class declarator: ret={}", ret
);
1328 BT_ASSERT(field_decl
);
1329 field_name
= g_quark_to_string(qfield_name
);
1331 /* Check if field with same name already exists */
1332 if (ctf_field_class_struct_borrow_member_by_name(struct_decl
, field_name
)) {
1333 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1334 "Duplicate field in structure field class: "
1335 "field-name=\"{}\"",
1341 /* Add field to structure */
1342 ctf_field_class_struct_append_member(struct_decl
, field_name
, field_decl
);
1349 ctf_field_class_destroy(field_decl
);
1354 static int visit_variant_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1355 struct ctf_field_class_variant
*variant_decl
,
1356 struct ctf_node
*cls_specifier_list
,
1357 struct bt_list_head
*field_class_declarators
)
1360 struct ctf_node
*iter
;
1361 struct ctf_field_class
*field_decl
= NULL
;
1363 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1366 const char *field_name
;
1368 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1371 BT_ASSERT(!field_decl
);
1372 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1373 "Cannot visit field class declarator: ret={}", ret
);
1377 BT_ASSERT(field_decl
);
1378 field_name
= g_quark_to_string(qfield_name
);
1380 /* Check if field with same name already exists */
1381 if (ctf_field_class_variant_borrow_option_by_name(variant_decl
, field_name
)) {
1382 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1383 "Duplicate field in variant field class: "
1384 "field-name=\"{}\"",
1390 /* Add field to structure */
1391 ctf_field_class_variant_append_option(variant_decl
, field_name
, field_decl
);
1398 ctf_field_class_destroy(field_decl
);
1403 static int visit_field_class_def(struct ctf_visitor_generate_ir
*ctx
,
1404 struct ctf_node
*cls_specifier_list
,
1405 struct bt_list_head
*field_class_declarators
)
1409 struct ctf_node
*iter
;
1410 struct ctf_field_class
*class_decl
= NULL
;
1412 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1413 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qidentifier
, iter
, &class_decl
,
1416 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit field class declarator: ret={}", ret
);
1421 /* Do not allow field class def and alias of untagged variants */
1422 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1423 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1425 if (var_fc
->tag_path
.path
->len
== 0) {
1426 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1427 iter
, "Type definition of untagged variant field class is not allowed.");
1433 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qidentifier
),
1436 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot register field class alias: name=\"{}\"",
1437 g_quark_to_string(qidentifier
));
1443 ctf_field_class_destroy(class_decl
);
1448 static int visit_field_class_alias(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*target
,
1449 struct ctf_node
*alias
)
1453 struct ctf_node
*node
;
1454 GQuark qdummy_field_name
;
1455 struct ctf_field_class
*class_decl
= NULL
;
1457 /* Create target field class */
1458 if (bt_list_empty(&target
->u
.field_class_alias_target
.field_class_declarators
)) {
1461 node
= _BT_LIST_FIRST_ENTRY(&target
->u
.field_class_alias_target
.field_class_declarators
,
1462 struct ctf_node
, siblings
);
1465 ret
= visit_field_class_declarator(
1466 ctx
, target
->u
.field_class_alias_target
.field_class_specifier_list
, &qdummy_field_name
,
1467 node
, &class_decl
, NULL
);
1469 BT_ASSERT(!class_decl
);
1470 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot visit field class declarator: ret={}", ret
);
1474 /* Do not allow field class def and alias of untagged variants */
1475 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1476 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1478 if (var_fc
->tag_path
.path
->len
== 0) {
1479 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1480 target
, "Type definition of untagged variant field class is not allowed.");
1487 * The semantic validator does not check whether the target is
1488 * abstract or not (if it has an identifier). Check it here.
1490 if (qdummy_field_name
!= 0) {
1491 _BT_CPPLOGE_APPEND_CAUSE_NODE(target
, "Expecting empty identifier: id=\"{}\"",
1492 g_quark_to_string(qdummy_field_name
));
1497 /* Create alias identifier */
1498 node
= _BT_LIST_FIRST_ENTRY(&alias
->u
.field_class_alias_name
.field_class_declarators
,
1499 struct ctf_node
, siblings
);
1500 qalias
= create_class_alias_identifier(
1501 ctx
, alias
->u
.field_class_alias_name
.field_class_specifier_list
, node
);
1502 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qalias
), class_decl
);
1504 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot register class alias: name=\"{}\"",
1505 g_quark_to_string(qalias
));
1510 ctf_field_class_destroy(class_decl
);
1515 static int visit_struct_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
1516 struct ctf_field_class_struct
*struct_decl
)
1520 switch (entry_node
->type
) {
1522 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1523 &entry_node
->u
.field_class_def
.field_class_declarators
);
1525 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1526 entry_node
, "Cannot add field class found in structure field class: ret={}", ret
);
1530 case NODE_TYPEALIAS
:
1531 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1532 entry_node
->u
.field_class_alias
.alias
);
1534 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1535 entry_node
, "Cannot add field class alias found in structure field class: ret={}",
1540 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1542 ret
= visit_struct_decl_field(
1544 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1545 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1551 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type={}",
1561 static int visit_variant_decl_entry(struct ctf_visitor_generate_ir
*ctx
,
1562 struct ctf_node
*entry_node
,
1563 struct ctf_field_class_variant
*variant_decl
)
1567 switch (entry_node
->type
) {
1569 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1570 &entry_node
->u
.field_class_def
.field_class_declarators
);
1572 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1573 entry_node
, "Cannot add field class found in variant field class: ret={}", ret
);
1577 case NODE_TYPEALIAS
:
1578 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1579 entry_node
->u
.field_class_alias
.alias
);
1581 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1582 entry_node
, "Cannot add field class alias found in variant field class: ret={}",
1587 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1589 ret
= visit_variant_decl_field(
1591 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1592 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1598 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type={}",
1608 static int visit_struct_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1609 struct bt_list_head
*decl_list
, int has_body
,
1610 struct bt_list_head
*min_align
,
1611 struct ctf_field_class_struct
**struct_decl
)
1615 BT_ASSERT(struct_decl
);
1616 *struct_decl
= NULL
;
1618 /* For named struct (without body), lookup in declaration scope */
1621 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1622 "Bodyless structure field class: missing name.");
1627 *struct_decl
= ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, -1, true);
1628 if (!*struct_decl
) {
1629 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1630 ctx
->logger
, "Cannot find structure field class: name=\"struct {}\"", name
);
1635 struct ctf_node
*entry_node
;
1636 uint64_t min_align_value
= 0;
1639 if (ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, 1, false)) {
1640 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1642 "Structure field class already declared in local scope: "
1643 "name=\"struct {}\"",
1650 if (!bt_list_empty(min_align
)) {
1651 ret
= get_unary_unsigned(ctx
, min_align
, &min_align_value
);
1653 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1655 "Unexpected unary expression for structure field class's `align` attribute: "
1662 *struct_decl
= ctf_field_class_struct_create();
1663 BT_ASSERT(*struct_decl
);
1665 if (min_align_value
!= 0) {
1666 (*struct_decl
)->base
.alignment
= min_align_value
;
1669 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1671 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1672 ret
= visit_struct_decl_entry(ctx
, entry_node
, *struct_decl
);
1674 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
,
1675 "Cannot visit structure field class entry: "
1686 ret
= ctx_decl_scope_register_struct(ctx
->current_scope
, name
, *struct_decl
);
1688 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1690 "Cannot register structure field class in declaration scope: "
1691 "name=\"struct {}\", ret={}",
1701 ctf_field_class_destroy(&(*struct_decl
)->base
);
1702 *struct_decl
= NULL
;
1706 static int visit_variant_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1707 const char *tag
, struct bt_list_head
*decl_list
, int has_body
,
1708 struct ctf_field_class_variant
**variant_decl
)
1711 struct ctf_field_class_variant
*untagged_variant_decl
= NULL
;
1713 BT_ASSERT(variant_decl
);
1714 *variant_decl
= NULL
;
1716 /* For named variant (without body), lookup in declaration scope */
1719 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1720 "Bodyless variant field class: missing name.");
1725 untagged_variant_decl
= ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, -1, true);
1726 if (!untagged_variant_decl
) {
1727 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1728 ctx
->logger
, "Cannot find variant field class: name=\"variant {}\"", name
);
1733 struct ctf_node
*entry_node
;
1736 if (ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, 1, false)) {
1737 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1738 "Variant field class already declared in local scope: "
1739 "name=\"variant {}\"",
1746 untagged_variant_decl
= ctf_field_class_variant_create();
1747 BT_ASSERT(untagged_variant_decl
);
1748 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1750 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1751 ret
= visit_variant_decl_entry(ctx
, entry_node
, untagged_variant_decl
);
1753 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
,
1754 "Cannot visit variant field class entry: "
1765 ret
= ctx_decl_scope_register_variant(ctx
->current_scope
, name
, untagged_variant_decl
);
1767 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1769 "Cannot register variant field class in declaration scope: "
1770 "name=\"variant {}\", ret={}",
1778 * If tagged, create tagged variant and return; otherwise
1779 * return untagged variant.
1782 *variant_decl
= untagged_variant_decl
;
1783 untagged_variant_decl
= NULL
;
1786 * At this point, we have a fresh untagged variant; nobody
1787 * else owns it. Set its tag now.
1789 g_string_assign(untagged_variant_decl
->tag_ref
, tag
);
1790 *variant_decl
= untagged_variant_decl
;
1791 untagged_variant_decl
= NULL
;
1794 BT_ASSERT(!untagged_variant_decl
);
1795 BT_ASSERT(*variant_decl
);
1799 ctf_field_class_destroy(&untagged_variant_decl
->base
);
1800 untagged_variant_decl
= NULL
;
1801 ctf_field_class_destroy(&(*variant_decl
)->base
);
1802 *variant_decl
= NULL
;
1816 static int visit_enum_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*enumerator
,
1817 struct ctf_field_class_enum
*enum_decl
, struct uori
*last
)
1821 struct ctf_node
*iter
;
1822 struct uori start
= {
1836 const char *label
= enumerator
->u
.enumerator
.id
;
1837 struct bt_list_head
*values
= &enumerator
->u
.enumerator
.values
;
1839 bt_list_for_each_entry (iter
, values
, siblings
) {
1840 struct uori
*target
;
1842 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
1843 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
1844 "Wrong expression for enumeration field class label: "
1845 "node-type={}, label=\"{}\"",
1857 switch (iter
->u
.unary_expression
.type
) {
1858 case UNARY_SIGNED_CONSTANT
:
1859 target
->is_signed
= true;
1860 target
->value
.i
= iter
->u
.unary_expression
.u
.signed_constant
;
1862 case UNARY_UNSIGNED_CONSTANT
:
1863 target
->is_signed
= false;
1864 target
->value
.u
= iter
->u
.unary_expression
.u
.unsigned_constant
;
1867 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
1868 "Invalid enumeration field class entry: "
1869 "expecting constant signed or unsigned integer: "
1870 "node-type={}, label=\"{}\"",
1871 iter
->u
.unary_expression
.type
, label
);
1877 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1878 iter
, "Invalid enumeration field class entry: label=\"{}\"", label
);
1894 if (end
.is_signed
) {
1895 last
->value
.i
= end
.value
.i
+ 1;
1897 last
->value
.u
= end
.value
.u
+ 1;
1900 ctf_field_class_enum_map_range(enum_decl
, label
, start
.value
.u
, end
.value
.u
);
1907 static int visit_enum_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1908 struct ctf_node
*container_cls
, struct bt_list_head
*enumerator_list
,
1909 int has_body
, struct ctf_field_class_enum
**enum_decl
)
1913 struct ctf_field_class_int
*integer_decl
= NULL
;
1915 BT_ASSERT(enum_decl
);
1918 /* For named enum (without body), lookup in declaration scope */
1921 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1922 "Bodyless enumeration field class: missing name.");
1927 *enum_decl
= ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, -1, true);
1929 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1930 "Cannot find enumeration field class: "
1937 struct ctf_node
*iter
;
1938 struct uori last_value
= {
1947 if (ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, 1, false)) {
1948 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1950 "Enumeration field class already declared in local scope: "
1958 if (!container_cls
) {
1959 integer_decl
= ctf_field_class_as_int(
1960 ctx_decl_scope_lookup_alias(ctx
->current_scope
, "int", -1, true));
1961 if (!integer_decl
) {
1962 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1964 "Cannot find implicit `int` field class alias for enumeration field class.");
1969 ctf_field_class
*decl
;
1971 ret
= visit_field_class_declarator(ctx
, container_cls
, &qdummy_id
, NULL
, &decl
, NULL
);
1978 integer_decl
= ctf_field_class_as_int(decl
);
1981 BT_ASSERT(integer_decl
);
1983 if (integer_decl
->base
.base
.type
!= CTF_FIELD_CLASS_TYPE_INT
) {
1984 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1986 "Container field class for enumeration field class is not an integer field class: "
1988 integer_decl
->base
.base
.type
);
1993 *enum_decl
= ctf_field_class_enum_create();
1994 BT_ASSERT(*enum_decl
);
1995 (*enum_decl
)->base
.base
.base
.alignment
= integer_decl
->base
.base
.alignment
;
1996 ctf_field_class_int_copy_content(&(*enum_decl
)->base
, integer_decl
);
1997 last_value
.is_signed
= (*enum_decl
)->base
.is_signed
;
1999 bt_list_for_each_entry (iter
, enumerator_list
, siblings
) {
2000 ret
= visit_enum_decl_entry(ctx
, iter
, *enum_decl
, &last_value
);
2002 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
2003 "Cannot visit enumeration field class entry: "
2011 ret
= ctx_decl_scope_register_enum(ctx
->current_scope
, name
, *enum_decl
);
2013 BT_CPPLOGE_APPEND_CAUSE_SPEC(
2015 "Cannot register enumeration field class in declaration scope: "
2026 ctf_field_class_destroy(&(*enum_decl
)->base
.base
.base
);
2030 ctf_field_class_destroy(&integer_decl
->base
.base
);
2031 integer_decl
= NULL
;
2035 static int visit_field_class_specifier(struct ctf_visitor_generate_ir
*ctx
,
2036 struct ctf_node
*cls_specifier_list
,
2037 struct ctf_field_class
**decl
)
2040 GString
*str
= NULL
;
2043 str
= g_string_new("");
2044 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
2046 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2047 "Cannot get field class specifier list's name: ret={}", ret
);
2051 *decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, str
->str
, -1, true);
2053 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2054 "Cannot find field class alias: name=\"{}\"", str
->str
);
2062 ctf_field_class_destroy(*decl
);
2067 g_string_free(str
, TRUE
);
2073 static int visit_integer_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2074 struct ctf_field_class_int
**integer_decl
)
2079 struct ctf_node
*expression
;
2080 uint64_t alignment
= 0, size
= 0;
2081 struct ctf_clock_class
*mapped_clock_class
= NULL
;
2082 enum ctf_encoding encoding
= CTF_ENCODING_NONE
;
2083 bt_field_class_integer_preferred_display_base base
=
2084 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2085 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2087 *integer_decl
= NULL
;
2089 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2090 struct ctf_node
*left
, *right
;
2092 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2094 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2096 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2097 _BT_CPPLOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type={}",
2098 left
->u
.unary_expression
.type
);
2103 if (strcmp(left
->u
.unary_expression
.u
.string
, "signed") == 0) {
2104 if (_IS_SET(&set
, _INTEGER_SIGNED_SET
)) {
2105 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "signed", "integer field class");
2110 signedness
= get_boolean(ctx
, right
);
2111 if (signedness
< 0) {
2112 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2114 "Invalid boolean value for integer field class's `signed` attribute: "
2121 _SET(&set
, _INTEGER_SIGNED_SET
);
2122 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2123 if (_IS_SET(&set
, _INTEGER_BYTE_ORDER_SET
)) {
2124 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order", "integer field class");
2129 byte_order
= get_real_byte_order(ctx
, right
);
2130 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2131 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2133 "Invalid `byte_order` attribute in integer field class: "
2140 _SET(&set
, _INTEGER_BYTE_ORDER_SET
);
2141 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "size") == 0) {
2142 if (_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2143 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "size", "integer field class");
2148 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2149 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2150 "Invalid `size` attribute in integer field class: "
2151 "expecting unsigned constant integer: "
2153 right
->u
.unary_expression
.type
);
2158 size
= right
->u
.unary_expression
.u
.unsigned_constant
;
2160 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2161 "Invalid `size` attribute in integer field class: "
2162 "expecting positive constant integer: "
2167 } else if (size
> 64) {
2168 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2170 "Invalid `size` attribute in integer field class: "
2171 "integer fields over 64 bits are not supported as of this version: "
2178 _SET(&set
, _INTEGER_SIZE_SET
);
2179 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2180 if (_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2181 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "align", "integer field class");
2186 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2187 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2188 "Invalid `align` attribute in integer field class: "
2189 "expecting unsigned constant integer: "
2191 right
->u
.unary_expression
.type
);
2196 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2197 if (!is_align_valid(alignment
)) {
2198 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2199 "Invalid `align` attribute in integer field class: "
2200 "expecting power of two: "
2207 _SET(&set
, _INTEGER_ALIGN_SET
);
2208 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "base") == 0) {
2209 if (_IS_SET(&set
, _INTEGER_BASE_SET
)) {
2210 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "base", "integer field class");
2215 switch (right
->u
.unary_expression
.type
) {
2216 case UNARY_UNSIGNED_CONSTANT
:
2218 uint64_t constant
= right
->u
.unary_expression
.u
.unsigned_constant
;
2222 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2225 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2228 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2231 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2234 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2236 "Invalid `base` attribute in integer field class: "
2238 right
->u
.unary_expression
.u
.unsigned_constant
);
2247 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2249 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2251 "Unexpected unary expression for integer field class's `base` attribute.");
2256 if (strcmp(s_right
, "decimal") == 0 || strcmp(s_right
, "dec") == 0 ||
2257 strcmp(s_right
, "d") == 0 || strcmp(s_right
, "i") == 0 ||
2258 strcmp(s_right
, "u") == 0) {
2259 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2260 } else if (strcmp(s_right
, "hexadecimal") == 0 || strcmp(s_right
, "hex") == 0 ||
2261 strcmp(s_right
, "x") == 0 || strcmp(s_right
, "X") == 0 ||
2262 strcmp(s_right
, "p") == 0) {
2263 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2264 } else if (strcmp(s_right
, "octal") == 0 || strcmp(s_right
, "oct") == 0 ||
2265 strcmp(s_right
, "o") == 0) {
2266 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2267 } else if (strcmp(s_right
, "binary") == 0 || strcmp(s_right
, "b") == 0) {
2268 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2270 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2272 "Unexpected unary expression for integer field class's `base` attribute: "
2284 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2285 right
, "Invalid `base` attribute in integer field class: "
2286 "expecting unsigned constant integer or unary string.");
2291 _SET(&set
, _INTEGER_BASE_SET
);
2292 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2295 if (_IS_SET(&set
, _INTEGER_ENCODING_SET
)) {
2296 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "integer field class");
2301 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2302 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2303 right
, "Invalid `encoding` attribute in integer field class: "
2304 "expecting unary string.");
2309 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2311 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2313 "Unexpected unary expression for integer field class's `encoding` attribute.");
2318 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2319 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2320 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2321 encoding
= CTF_ENCODING_UTF8
;
2322 } else if (strcmp(s_right
, "none") == 0) {
2323 encoding
= CTF_ENCODING_NONE
;
2325 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2327 "Invalid `encoding` attribute in integer field class: "
2328 "unknown encoding: encoding=\"{}\"",
2336 _SET(&set
, _INTEGER_ENCODING_SET
);
2337 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "map") == 0) {
2338 const char *clock_name
;
2340 if (_IS_SET(&set
, _INTEGER_MAP_SET
)) {
2341 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "map", "integer field class");
2346 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2347 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2348 "Invalid `map` attribute in integer field class: "
2349 "expecting unary string.");
2354 clock_name
= get_map_clock_name_value(&expression
->u
.ctf_expression
.right
);
2357 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2360 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2362 "Unexpected unary expression for integer field class's `map` attribute.");
2367 _BT_CPPLOGE_NODE(right
,
2368 "Invalid `map` attribute in integer field class: "
2369 "cannot find clock class at this point: name=\"{}\"",
2371 _SET(&set
, _INTEGER_MAP_SET
);
2376 mapped_clock_class
=
2377 ctf_trace_class_borrow_clock_class_by_name(ctx
->ctf_tc
, clock_name
);
2378 if (!mapped_clock_class
) {
2379 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2380 "Invalid `map` attribute in integer field class: "
2381 "cannot find clock class at this point: name=\"{}\"",
2387 _SET(&set
, _INTEGER_MAP_SET
);
2389 _BT_CPPLOGW_NODE(left
,
2390 "Unknown attribute in integer field class: "
2392 left
->u
.unary_expression
.u
.string
);
2396 if (!_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2397 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
2398 "Missing `size` attribute in integer field class.");
2403 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2404 if (size
% CHAR_BIT
) {
2405 /* Bit-packed alignment */
2408 /* Byte-packed alignment */
2409 alignment
= CHAR_BIT
;
2413 *integer_decl
= ctf_field_class_int_create();
2414 BT_ASSERT(*integer_decl
);
2415 (*integer_decl
)->base
.base
.alignment
= alignment
;
2416 (*integer_decl
)->base
.byte_order
= byte_order
;
2417 (*integer_decl
)->base
.size
= size
;
2418 (*integer_decl
)->is_signed
= (signedness
> 0);
2419 (*integer_decl
)->disp_base
= base
;
2420 (*integer_decl
)->encoding
= encoding
;
2421 (*integer_decl
)->mapped_clock_class
= mapped_clock_class
;
2425 ctf_field_class_destroy(&(*integer_decl
)->base
.base
);
2426 *integer_decl
= NULL
;
2430 static int visit_floating_point_number_decl(struct ctf_visitor_generate_ir
*ctx
,
2431 struct bt_list_head
*expressions
,
2432 struct ctf_field_class_float
**float_decl
)
2436 struct ctf_node
*expression
;
2437 uint64_t alignment
= 1, exp_dig
= 0, mant_dig
= 0;
2438 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2442 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2443 struct ctf_node
*left
, *right
;
2445 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2447 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2449 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2450 _BT_CPPLOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type={}",
2451 left
->u
.unary_expression
.type
);
2456 if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2457 if (_IS_SET(&set
, _FLOAT_BYTE_ORDER_SET
)) {
2458 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order",
2459 "floating point number field class");
2464 byte_order
= get_real_byte_order(ctx
, right
);
2465 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2466 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2468 "Invalid `byte_order` attribute in floating point number field class: "
2475 _SET(&set
, _FLOAT_BYTE_ORDER_SET
);
2476 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "exp_dig") == 0) {
2477 if (_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2478 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "exp_dig",
2479 "floating point number field class");
2484 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2485 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2487 "Invalid `exp_dig` attribute in floating point number field class: "
2488 "expecting unsigned constant integer: "
2490 right
->u
.unary_expression
.type
);
2495 exp_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2496 _SET(&set
, _FLOAT_EXP_DIG_SET
);
2497 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "mant_dig") == 0) {
2498 if (_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2499 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "mant_dig",
2500 "floating point number field class");
2505 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2506 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2508 "Invalid `mant_dig` attribute in floating point number field class: "
2509 "expecting unsigned constant integer: "
2511 right
->u
.unary_expression
.type
);
2516 mant_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2517 _SET(&set
, _FLOAT_MANT_DIG_SET
);
2518 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2519 if (_IS_SET(&set
, _FLOAT_ALIGN_SET
)) {
2520 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "align",
2521 "floating point number field class");
2526 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2527 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2529 "Invalid `align` attribute in floating point number field class: "
2530 "expecting unsigned constant integer: "
2532 right
->u
.unary_expression
.type
);
2537 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2539 if (!is_align_valid(alignment
)) {
2540 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2542 "Invalid `align` attribute in floating point number field class: "
2543 "expecting power of two: "
2550 _SET(&set
, _FLOAT_ALIGN_SET
);
2552 _BT_CPPLOGW_NODE(left
,
2553 "Unknown attribute in floating point number field class: "
2555 left
->u
.unary_expression
.u
.string
);
2559 if (!_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2560 BT_CPPLOGE_APPEND_CAUSE_SPEC(
2561 ctx
->logger
, "Missing `mant_dig` attribute in floating point number field class.");
2566 if (!_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2567 BT_CPPLOGE_APPEND_CAUSE_SPEC(
2568 ctx
->logger
, "Missing `exp_dig` attribute in floating point number field class.");
2573 if (mant_dig
!= 24 && mant_dig
!= 53) {
2574 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "`mant_dig` attribute: expecting 24 or 53.");
2579 if (mant_dig
== 24 && exp_dig
!= 8) {
2580 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
2581 "`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2586 if (mant_dig
== 53 && exp_dig
!= 11) {
2587 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
2588 "`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2593 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2594 if ((mant_dig
+ exp_dig
) % CHAR_BIT
) {
2595 /* Bit-packed alignment */
2598 /* Byte-packed alignment */
2599 alignment
= CHAR_BIT
;
2603 *float_decl
= ctf_field_class_float_create();
2604 BT_ASSERT(*float_decl
);
2605 (*float_decl
)->base
.base
.alignment
= alignment
;
2606 (*float_decl
)->base
.byte_order
= byte_order
;
2607 (*float_decl
)->base
.size
= mant_dig
+ exp_dig
;
2611 ctf_field_class_destroy(&(*float_decl
)->base
.base
);
2616 static int visit_string_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2617 struct ctf_field_class_string
**string_decl
)
2621 struct ctf_node
*expression
;
2622 enum ctf_encoding encoding
= CTF_ENCODING_UTF8
;
2624 *string_decl
= NULL
;
2626 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2627 struct ctf_node
*left
, *right
;
2629 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2631 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2633 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2634 _BT_CPPLOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type={}",
2635 left
->u
.unary_expression
.type
);
2640 if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2643 if (_IS_SET(&set
, _STRING_ENCODING_SET
)) {
2644 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "string field class");
2649 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2650 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2651 "Invalid `encoding` attribute in string field class: "
2652 "expecting unary string.");
2657 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2659 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2661 "Unexpected unary expression for string field class's `encoding` attribute.");
2666 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2667 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2668 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2669 encoding
= CTF_ENCODING_UTF8
;
2670 } else if (strcmp(s_right
, "none") == 0) {
2671 encoding
= CTF_ENCODING_NONE
;
2673 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2674 "Invalid `encoding` attribute in string field class: "
2675 "unknown encoding: encoding=\"{}\"",
2683 _SET(&set
, _STRING_ENCODING_SET
);
2685 _BT_CPPLOGW_NODE(left
,
2686 "Unknown attribute in string field class: "
2688 left
->u
.unary_expression
.u
.string
);
2692 *string_decl
= ctf_field_class_string_create();
2693 BT_ASSERT(*string_decl
);
2694 (*string_decl
)->encoding
= encoding
;
2698 ctf_field_class_destroy(&(*string_decl
)->base
);
2699 *string_decl
= NULL
;
2703 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
2704 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
)
2707 struct ctf_node
*first
, *node
;
2711 if (ts_list
->type
!= NODE_TYPE_SPECIFIER_LIST
) {
2712 _BT_CPPLOGE_APPEND_CAUSE_NODE(ts_list
, "Unexpected node type: node-type={}", ts_list
->type
);
2717 first
= _BT_LIST_FIRST_ENTRY(&ts_list
->u
.field_class_specifier_list
.head
, struct ctf_node
,
2719 if (first
->type
!= NODE_TYPE_SPECIFIER
) {
2720 _BT_CPPLOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type={}", first
->type
);
2725 node
= first
->u
.field_class_specifier
.node
;
2727 switch (first
->u
.field_class_specifier
.type
) {
2728 case TYPESPEC_INTEGER
:
2730 ctf_field_class_int
*int_decl
;
2732 ret
= visit_integer_decl(ctx
, &node
->u
.integer
.expressions
, &int_decl
);
2734 BT_ASSERT(!int_decl
);
2738 *decl
= &int_decl
->base
.base
;
2741 case TYPESPEC_FLOATING_POINT
:
2743 ctf_field_class_float
*float_decl
;
2746 visit_floating_point_number_decl(ctx
, &node
->u
.floating_point
.expressions
, &float_decl
);
2748 BT_ASSERT(!float_decl
);
2752 *decl
= &float_decl
->base
.base
;
2755 case TYPESPEC_STRING
:
2757 ctf_field_class_string
*string_decl
;
2759 ret
= visit_string_decl(ctx
, &node
->u
.string
.expressions
, &string_decl
);
2761 BT_ASSERT(!string_decl
);
2765 *decl
= &string_decl
->base
;
2768 case TYPESPEC_STRUCT
:
2770 ctf_field_class_struct
*struct_decl
;
2772 ret
= visit_struct_decl(ctx
, node
->u
._struct
.name
, &node
->u
._struct
.declaration_list
,
2773 node
->u
._struct
.has_body
, &node
->u
._struct
.min_align
, &struct_decl
);
2775 BT_ASSERT(!struct_decl
);
2779 *decl
= &struct_decl
->base
;
2782 case TYPESPEC_VARIANT
:
2784 ctf_field_class_variant
*variant_decl
;
2786 ret
= visit_variant_decl(ctx
, node
->u
.variant
.name
, node
->u
.variant
.choice
,
2787 &node
->u
.variant
.declaration_list
, node
->u
.variant
.has_body
,
2790 BT_ASSERT(!variant_decl
);
2794 *decl
= &variant_decl
->base
;
2799 ctf_field_class_enum
*enum_decl
;
2801 ret
= visit_enum_decl(ctx
, node
->u
._enum
.enum_id
, node
->u
._enum
.container_field_class
,
2802 &node
->u
._enum
.enumerator_list
, node
->u
._enum
.has_body
, &enum_decl
);
2804 BT_ASSERT(!enum_decl
);
2808 *decl
= &enum_decl
->base
.base
.base
;
2813 case TYPESPEC_SHORT
:
2816 case TYPESPEC_FLOAT
:
2817 case TYPESPEC_DOUBLE
:
2818 case TYPESPEC_SIGNED
:
2819 case TYPESPEC_UNSIGNED
:
2821 case TYPESPEC_COMPLEX
:
2822 case TYPESPEC_IMAGINARY
:
2823 case TYPESPEC_CONST
:
2824 case TYPESPEC_ID_TYPE
:
2825 ret
= visit_field_class_specifier(ctx
, ts_list
, decl
);
2827 _BT_CPPLOGE_APPEND_CAUSE_NODE(first
, "Cannot visit field class specifier: ret={}", ret
);
2833 _BT_CPPLOGE_APPEND_CAUSE_NODE(first
, "Unexpected field class specifier type: node-type={}",
2834 first
->u
.field_class_specifier
.type
);
2843 ctf_field_class_destroy(*decl
);
2848 static int visit_event_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
2849 struct ctf_event_class
*event_class
, uint64_t *stream_id
,
2855 switch (node
->type
) {
2857 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
2858 &node
->u
.field_class_def
.field_class_declarators
);
2860 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in event class.");
2864 case NODE_TYPEALIAS
:
2865 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
2866 node
->u
.field_class_alias
.alias
);
2868 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
2869 "Cannot add field class alias found in event class.");
2873 case NODE_CTF_EXPRESSION
:
2875 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
2877 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
2882 if (strcmp(left
, "name") == 0) {
2883 /* This is already known at this stage */
2884 if (_IS_SET(set
, _EVENT_NAME_SET
)) {
2885 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "name", "event class");
2890 _SET(set
, _EVENT_NAME_SET
);
2891 } else if (strcmp(left
, "id") == 0) {
2894 if (_IS_SET(set
, _EVENT_ID_SET
)) {
2895 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "event class");
2900 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
2901 /* Only read "id" if get_unary_unsigned() succeeded. */
2902 if (ret
|| (!ret
&& id
< 0)) {
2903 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2904 node
, "Unexpected unary expression for event class's `id` attribute.");
2909 event_class
->id
= id
;
2910 _SET(set
, _EVENT_ID_SET
);
2911 } else if (strcmp(left
, "stream_id") == 0) {
2912 if (_IS_SET(set
, _EVENT_STREAM_ID_SET
)) {
2913 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "stream_id", "event class");
2918 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, stream_id
);
2921 * Only read "stream_id" if get_unary_unsigned()
2925 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2926 node
, "Unexpected unary expression for event class's `stream_id` attribute.");
2931 _SET(set
, _EVENT_STREAM_ID_SET
);
2932 } else if (strcmp(left
, "context") == 0) {
2933 if (_IS_SET(set
, _EVENT_CONTEXT_SET
)) {
2934 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate `context` entry in event class.");
2939 ret
= visit_field_class_specifier_list(
2940 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2941 &event_class
->spec_context_fc
);
2943 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
2944 "Cannot create event class's context field class.");
2948 BT_ASSERT(event_class
->spec_context_fc
);
2949 _SET(set
, _EVENT_CONTEXT_SET
);
2950 } else if (strcmp(left
, "fields") == 0) {
2951 if (_IS_SET(set
, _EVENT_FIELDS_SET
)) {
2952 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate `fields` entry in event class.");
2957 ret
= visit_field_class_specifier_list(
2958 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2959 &event_class
->payload_fc
);
2961 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
2962 "Cannot create event class's payload field class.");
2966 BT_ASSERT(event_class
->payload_fc
);
2967 _SET(set
, _EVENT_FIELDS_SET
);
2968 } else if (strcmp(left
, "loglevel") == 0) {
2969 uint64_t loglevel_value
;
2970 bool is_log_level_known
= true;
2971 bt_event_class_log_level log_level
;
2973 if (_IS_SET(set
, _EVENT_LOG_LEVEL_SET
)) {
2974 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "loglevel", "event class");
2979 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &loglevel_value
);
2981 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2982 node
, "Unexpected unary expression for event class's `loglevel` attribute.");
2987 switch (loglevel_value
) {
2989 log_level
= BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
;
2992 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ALERT
;
2995 log_level
= BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
;
2998 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ERROR
;
3001 log_level
= BT_EVENT_CLASS_LOG_LEVEL_WARNING
;
3004 log_level
= BT_EVENT_CLASS_LOG_LEVEL_NOTICE
;
3007 log_level
= BT_EVENT_CLASS_LOG_LEVEL_INFO
;
3010 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
;
3013 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
;
3016 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
;
3019 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
;
3022 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
;
3025 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
;
3028 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
;
3031 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG
;
3034 is_log_level_known
= false;
3037 "Not setting event class's log level because its value is unknown: "
3042 if (is_log_level_known
) {
3043 ctf_event_class_set_log_level(event_class
, log_level
);
3046 _SET(set
, _EVENT_LOG_LEVEL_SET
);
3047 } else if (strcmp(left
, "model.emf.uri") == 0) {
3050 if (_IS_SET(set
, _EVENT_MODEL_EMF_URI_SET
)) {
3051 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "model.emf.uri", "event class");
3056 right
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.right
);
3058 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3060 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3065 if (strlen(right
) == 0) {
3066 _BT_CPPLOGW_NODE(node
, "Not setting event class's EMF URI because it's empty.");
3068 g_string_assign(event_class
->emf_uri
, right
);
3072 _SET(set
, _EVENT_MODEL_EMF_URI_SET
);
3074 _BT_CPPLOGW_NODE(node
,
3075 "Unknown attribute in event class: "
3098 static char *get_event_decl_name(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3102 struct ctf_node
*iter
;
3103 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3105 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3106 if (iter
->type
!= NODE_CTF_EXPRESSION
) {
3110 left
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.left
);
3112 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot concatenate unary strings.");
3116 if (strcmp(left
, "name") == 0) {
3117 name
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.right
);
3119 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3120 iter
, "Unexpected unary expression for event class's `name` attribute.");
3140 static int visit_event_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3144 struct ctf_node
*iter
;
3145 uint64_t stream_id
= 0;
3146 char *event_name
= NULL
;
3147 struct ctf_event_class
*event_class
= NULL
;
3148 struct ctf_stream_class
*stream_class
= NULL
;
3149 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3150 bool pop_scope
= false;
3152 if (node
->visited
) {
3156 node
->visited
= TRUE
;
3157 event_name
= get_event_decl_name(ctx
, node
);
3159 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `name` attribute in event class.");
3164 event_class
= ctf_event_class_create();
3165 BT_ASSERT(event_class
);
3166 g_string_assign(event_class
->name
, event_name
);
3167 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3170 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3171 ret
= visit_event_decl_entry(ctx
, iter
, event_class
, &stream_id
, &set
);
3173 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
3174 "Cannot visit event class's entry: "
3181 if (!_IS_SET(&set
, _EVENT_STREAM_ID_SET
)) {
3183 * Allow missing stream_id if there is only a single
3186 switch (ctx
->ctf_tc
->stream_classes
->len
) {
3188 /* Create implicit stream class if there's none */
3190 stream_class
= ctf_stream_class_create();
3191 BT_ASSERT(stream_class
);
3192 stream_class
->id
= stream_id
;
3193 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3196 /* Single stream class: get its ID */
3197 stream_class
= (ctf_stream_class
*) ctx
->ctf_tc
->stream_classes
->pdata
[0];
3198 stream_id
= stream_class
->id
;
3201 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `stream_id` attribute in event class.");
3207 /* We have the stream ID now; get the stream class if found */
3208 if (!stream_class
) {
3209 stream_class
= ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_id
);
3210 if (!stream_class
) {
3211 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3212 "Cannot find stream class at this point: "
3220 BT_ASSERT(stream_class
);
3222 if (!_IS_SET(&set
, _EVENT_ID_SET
)) {
3223 /* Allow only one event without ID per stream */
3224 if (stream_class
->event_classes
->len
!= 0) {
3225 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `id` attribute in event class.");
3231 event_class
->id
= 0;
3234 if (ctf_stream_class_borrow_event_class_by_id(stream_class
, event_class
->id
)) {
3235 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3236 "Duplicate event class (same ID) in the same stream class: "
3243 ctf_stream_class_append_event_class(stream_class
, event_class
);
3248 ctf_event_class_destroy(event_class
);
3265 static int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3266 struct ctf_field_class
*fc
)
3268 struct ctf_clock_class
*clock_class_to_map_to
= NULL
;
3269 uint64_t clock_class_count
;
3275 if (fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&& fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3279 ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
3281 if (int_fc
->mapped_clock_class
) {
3282 /* Already mapped */
3286 clock_class_count
= ctx
->ctf_tc
->clock_classes
->len
;
3288 switch (clock_class_count
) {
3291 * No clock class exists in the trace at this point. Create an
3292 * implicit one at 1 GHz, named `default`, and use this clock
3295 clock_class_to_map_to
= ctf_clock_class_create();
3296 BT_ASSERT(clock_class_to_map_to
);
3297 clock_class_to_map_to
->frequency
= UINT64_C(1000000000);
3298 g_string_assign(clock_class_to_map_to
->name
, "default");
3299 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock_class_to_map_to
);
3303 * Only one clock class exists in the trace at this point: use
3306 clock_class_to_map_to
= (ctf_clock_class
*) ctx
->ctf_tc
->clock_classes
->pdata
[0];
3310 * Timestamp field not mapped to a clock class and there's more
3311 * than one clock class in the trace: this is an error.
3313 BT_CPPLOGE_APPEND_CAUSE_SPEC(
3314 ctx
->logger
, "Timestamp field found with no mapped clock class, "
3315 "but there's more than one clock class in the trace at this point.");
3319 BT_ASSERT(clock_class_to_map_to
);
3320 int_fc
->mapped_clock_class
= clock_class_to_map_to
;
3325 static int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3326 struct ctf_field_class
*root_fc
,
3327 const char *field_name
)
3331 struct ctf_field_class_struct
*struct_fc
= (ctf_field_class_struct
*) root_fc
;
3332 struct ctf_field_class_variant
*var_fc
= (ctf_field_class_variant
*) root_fc
;
3338 if (root_fc
->type
!= CTF_FIELD_CLASS_TYPE_STRUCT
&&
3339 root_fc
->type
!= CTF_FIELD_CLASS_TYPE_VARIANT
) {
3343 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3344 count
= struct_fc
->members
->len
;
3346 count
= var_fc
->options
->len
;
3349 for (i
= 0; i
< count
; i
++) {
3350 struct ctf_named_field_class
*named_fc
= NULL
;
3352 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3353 named_fc
= ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
3354 } else if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
3355 named_fc
= ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
3360 if (strcmp(named_fc
->name
->str
, field_name
) == 0) {
3361 ret
= auto_map_field_to_trace_clock_class(ctx
, named_fc
->fc
);
3363 BT_CPPLOGE_APPEND_CAUSE_SPEC(
3365 "Cannot automatically map field to trace's clock class: "
3366 "field-name=\"{}\"",
3372 ret
= auto_map_fields_to_trace_clock_class(ctx
, named_fc
->fc
, field_name
);
3374 BT_CPPLOGE_APPEND_CAUSE_SPEC(
3376 "Cannot automatically map structure or variant field class's fields to trace's clock class: "
3377 "field-name=\"{}\", root-field-name=\"{}\"",
3378 field_name
, named_fc
->name
->str
);
3387 static int visit_stream_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3388 struct ctf_stream_class
*stream_class
, int *set
)
3393 switch (node
->type
) {
3395 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3396 &node
->u
.field_class_def
.field_class_declarators
);
3398 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in stream class.");
3402 case NODE_TYPEALIAS
:
3403 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3404 node
->u
.field_class_alias
.alias
);
3406 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3407 "Cannot add field class alias found in stream class.");
3411 case NODE_CTF_EXPRESSION
:
3413 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3415 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3420 if (strcmp(left
, "id") == 0) {
3423 if (_IS_SET(set
, _STREAM_ID_SET
)) {
3424 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "stream declaration");
3429 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
3431 /* Only read "id" if get_unary_unsigned() succeeded. */
3432 if (ret
|| (!ret
&& id
< 0)) {
3433 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3434 node
, "Unexpected unary expression for stream class's `id` attribute.");
3439 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, id
)) {
3440 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate stream class (same ID): id={}", id
);
3445 stream_class
->id
= id
;
3446 _SET(set
, _STREAM_ID_SET
);
3447 } else if (strcmp(left
, "event.header") == 0) {
3448 if (_IS_SET(set
, _STREAM_EVENT_HEADER_SET
)) {
3449 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3450 "Duplicate `event.header` entry in stream class.");
3455 ret
= visit_field_class_specifier_list(
3456 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3457 &stream_class
->event_header_fc
);
3459 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3460 node
, "Cannot create stream class's event header field class.");
3464 BT_ASSERT(stream_class
->event_header_fc
);
3465 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->event_header_fc
,
3468 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3470 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3474 _SET(set
, _STREAM_EVENT_HEADER_SET
);
3475 } else if (strcmp(left
, "event.context") == 0) {
3476 if (_IS_SET(set
, _STREAM_EVENT_CONTEXT_SET
)) {
3477 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3478 "Duplicate `event.context` entry in stream class.");
3483 ret
= visit_field_class_specifier_list(
3484 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3485 &stream_class
->event_common_context_fc
);
3487 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3488 node
, "Cannot create stream class's event context field class.");
3492 BT_ASSERT(stream_class
->event_common_context_fc
);
3493 _SET(set
, _STREAM_EVENT_CONTEXT_SET
);
3494 } else if (strcmp(left
, "packet.context") == 0) {
3495 if (_IS_SET(set
, _STREAM_PACKET_CONTEXT_SET
)) {
3496 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3497 "Duplicate `packet.context` entry in stream class.");
3502 ret
= visit_field_class_specifier_list(
3503 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3504 &stream_class
->packet_context_fc
);
3506 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3507 node
, "Cannot create stream class's packet context field class.");
3511 BT_ASSERT(stream_class
->packet_context_fc
);
3512 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3515 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3517 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3521 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3524 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3526 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3530 _SET(set
, _STREAM_PACKET_CONTEXT_SET
);
3532 _BT_CPPLOGW_NODE(node
,
3533 "Unknown attribute in stream class: "
3555 static int visit_stream_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3559 struct ctf_node
*iter
;
3560 struct ctf_stream_class
*stream_class
= NULL
;
3561 struct bt_list_head
*decl_list
= &node
->u
.stream
.declaration_list
;
3563 if (node
->visited
) {
3567 node
->visited
= TRUE
;
3568 stream_class
= ctf_stream_class_create();
3569 BT_ASSERT(stream_class
);
3570 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3572 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3573 ret
= visit_stream_decl_entry(ctx
, iter
, stream_class
, &set
);
3575 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
3576 "Cannot visit stream class's entry: "
3586 if (_IS_SET(&set
, _STREAM_ID_SET
)) {
3587 /* Check that packet header has `stream_id` field */
3588 struct ctf_named_field_class
*named_fc
= NULL
;
3590 if (!ctx
->ctf_tc
->packet_header_fc
) {
3591 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Stream class has a `id` attribute, "
3592 "but trace has no packet header field class.");
3597 named_fc
= ctf_field_class_struct_borrow_member_by_name(
3598 ctf_field_class_as_struct(ctx
->ctf_tc
->packet_header_fc
), "stream_id");
3600 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3601 node
, "Stream class has a `id` attribute, "
3602 "but trace's packet header field class has no `stream_id` field.");
3607 if (named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3608 named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3609 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3611 "Stream class has a `id` attribute, "
3612 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3617 /* Allow only _one_ ID-less stream */
3618 if (ctx
->ctf_tc
->stream_classes
->len
!= 0) {
3619 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3621 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3626 /* Automatic ID: 0 */
3627 stream_class
->id
= 0;
3631 * Make sure that this stream class's ID is currently unique in
3634 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_class
->id
)) {
3635 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate stream class (same ID): id={}",
3641 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3642 stream_class
= NULL
;
3646 ctf_stream_class_destroy(stream_class
);
3647 stream_class
= NULL
;
3653 static int visit_trace_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3660 switch (node
->type
) {
3662 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3663 &node
->u
.field_class_def
.field_class_declarators
);
3665 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3666 "Cannot add field class found in trace (`trace` block).");
3670 case NODE_TYPEALIAS
:
3671 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3672 node
->u
.field_class_alias
.alias
);
3674 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3675 node
, "Cannot add field class alias found in trace (`trace` block).");
3679 case NODE_CTF_EXPRESSION
:
3681 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3683 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3688 if (strcmp(left
, "major") == 0) {
3689 if (_IS_SET(set
, _TRACE_MAJOR_SET
)) {
3690 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "major", "trace");
3695 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3697 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3698 node
, "Unexpected unary expression for trace's `major` attribute.");
3704 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3705 "Invalid trace's `minor` attribute: expecting 1.");
3710 ctx
->ctf_tc
->major
= val
;
3711 _SET(set
, _TRACE_MAJOR_SET
);
3712 } else if (strcmp(left
, "minor") == 0) {
3713 if (_IS_SET(set
, _TRACE_MINOR_SET
)) {
3714 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "minor", "trace");
3719 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3721 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3722 node
, "Unexpected unary expression for trace's `minor` attribute.");
3728 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3729 "Invalid trace's `minor` attribute: expecting 8.");
3734 ctx
->ctf_tc
->minor
= val
;
3735 _SET(set
, _TRACE_MINOR_SET
);
3736 } else if (strcmp(left
, "uuid") == 0) {
3737 if (_IS_SET(set
, _TRACE_UUID_SET
)) {
3738 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "uuid", "trace");
3743 ret
= get_unary_uuid(ctx
, &node
->u
.ctf_expression
.right
, ctx
->ctf_tc
->uuid
);
3745 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Invalid trace's `uuid` attribute.");
3749 ctx
->ctf_tc
->is_uuid_set
= true;
3750 _SET(set
, _TRACE_UUID_SET
);
3751 } else if (strcmp(left
, "byte_order") == 0) {
3752 /* Default byte order is already known at this stage */
3753 if (_IS_SET(set
, _TRACE_BYTE_ORDER_SET
)) {
3754 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
3759 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
!= CTF_BYTE_ORDER_UNKNOWN
);
3760 _SET(set
, _TRACE_BYTE_ORDER_SET
);
3761 } else if (strcmp(left
, "packet.header") == 0) {
3762 if (_IS_SET(set
, _TRACE_PACKET_HEADER_SET
)) {
3763 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate `packet.header` entry in trace.");
3768 ret
= visit_field_class_specifier_list(
3769 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3770 &ctx
->ctf_tc
->packet_header_fc
);
3772 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3773 "Cannot create trace's packet header field class.");
3777 BT_ASSERT(ctx
->ctf_tc
->packet_header_fc
);
3778 _SET(set
, _TRACE_PACKET_HEADER_SET
);
3780 _BT_CPPLOGW_NODE(node
,
3781 "Unknown attribute in stream class: "
3791 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Unknown expression in trace.");
3803 static int visit_trace_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3807 struct ctf_node
*iter
;
3808 struct bt_list_head
*decl_list
= &node
->u
.trace
.declaration_list
;
3810 if (node
->visited
) {
3814 node
->visited
= TRUE
;
3816 if (ctx
->is_trace_visited
) {
3817 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
3822 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3824 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3825 ret
= visit_trace_decl_entry(ctx
, iter
, &set
);
3827 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
3828 "Cannot visit trace's entry (`trace` block): "
3838 if (!_IS_SET(&set
, _TRACE_MAJOR_SET
)) {
3839 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `major` attribute in trace (`trace` block).");
3844 if (!_IS_SET(&set
, _TRACE_MINOR_SET
)) {
3845 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `minor` attribute in trace (`trace` block).");
3850 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3851 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3852 "Missing `byte_order` attribute in trace (`trace` block).");
3857 ctx
->is_trace_visited
= true;
3866 static int visit_env(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3870 struct ctf_node
*entry_node
;
3871 struct bt_list_head
*decl_list
= &node
->u
.env
.declaration_list
;
3873 if (node
->visited
) {
3877 node
->visited
= TRUE
;
3879 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
3880 struct bt_list_head
*right_head
= &entry_node
->u
.ctf_expression
.right
;
3882 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
3883 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
,
3884 "Wrong expression in environment entry: "
3891 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
3893 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot get environment entry's name.");
3898 if (is_unary_string(right_head
)) {
3899 char *right
= ctf_ast_concatenate_unary_strings(right_head
);
3902 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3904 "Unexpected unary expression for environment entry's value: "
3911 if (strcmp(left
, "tracer_name") == 0) {
3912 if (strncmp(right
, "lttng", 5) == 0) {
3913 BT_CPPLOGI_SPEC(ctx
->logger
,
3914 "Detected LTTng trace from `{}` environment value: "
3915 "tracer-name=\"{}\"",
3917 ctx
->is_lttng
= true;
3921 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
,
3924 } else if (is_unary_unsigned(right_head
) || is_unary_signed(right_head
)) {
3927 if (is_unary_unsigned(right_head
)) {
3928 ret
= get_unary_unsigned(ctx
, right_head
, (uint64_t *) &v
);
3930 ret
= get_unary_signed(right_head
, &v
);
3933 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3935 "Unexpected unary expression for environment entry's value: "
3942 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
,
3945 _BT_CPPLOGW_NODE(entry_node
,
3946 "Environment entry has unknown type: "
3963 static int set_trace_byte_order(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*trace_node
)
3968 struct ctf_node
*node
;
3969 struct bt_list_head
*decl_list
= &trace_node
->u
.trace
.declaration_list
;
3971 bt_list_for_each_entry (node
, decl_list
, siblings
) {
3972 if (node
->type
== NODE_CTF_EXPRESSION
) {
3973 struct ctf_node
*right_node
;
3975 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3977 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3982 if (strcmp(left
, "byte_order") == 0) {
3983 enum ctf_byte_order bo
;
3985 if (_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3986 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
3991 _SET(&set
, _TRACE_BYTE_ORDER_SET
);
3993 _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
3994 bo
= byte_order_from_unary_expr(ctx
, right_node
);
3995 if (bo
== CTF_BYTE_ORDER_UNKNOWN
) {
3996 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3997 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
3998 "expecting `le`, `be`, or `network`.");
4001 } else if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
4002 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4003 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4004 "cannot be set to `native` here.");
4009 ctx
->ctf_tc
->default_byte_order
= bo
;
4017 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4018 _BT_CPPLOGE_APPEND_CAUSE_NODE(trace_node
,
4019 "Missing `byte_order` attribute in trace (`trace` block).");
4031 static int visit_clock_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
4032 struct ctf_clock_class
*clock
, int *set
, int64_t *offset_seconds
,
4033 uint64_t *offset_cycles
)
4038 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4039 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type={}",
4045 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
4047 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot concatenate unary strings.");
4052 if (strcmp(left
, "name") == 0) {
4055 if (_IS_SET(set
, _CLOCK_NAME_SET
)) {
4056 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "name", "clock class");
4061 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4063 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4064 entry_node
, "Unexpected unary expression for clock class's `name` attribute.");
4069 g_string_assign(clock
->name
, right
);
4071 _SET(set
, _CLOCK_NAME_SET
);
4072 } else if (strcmp(left
, "uuid") == 0) {
4075 if (_IS_SET(set
, _CLOCK_UUID_SET
)) {
4076 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "uuid", "clock class");
4081 ret
= get_unary_uuid(ctx
, &entry_node
->u
.ctf_expression
.right
, uuid
);
4083 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Invalid clock class's `uuid` attribute.");
4087 clock
->has_uuid
= true;
4088 bt_uuid_copy(clock
->uuid
, uuid
);
4089 _SET(set
, _CLOCK_UUID_SET
);
4090 } else if (strcmp(left
, "description") == 0) {
4093 if (_IS_SET(set
, _CLOCK_DESCRIPTION_SET
)) {
4094 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "description", "clock class");
4099 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4101 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4103 "Unexpected unary expression for clock class's `description` attribute.");
4108 g_string_assign(clock
->description
, right
);
4110 _SET(set
, _CLOCK_DESCRIPTION_SET
);
4111 } else if (strcmp(left
, "freq") == 0) {
4112 uint64_t freq
= UINT64_C(-1);
4114 if (_IS_SET(set
, _CLOCK_FREQ_SET
)) {
4115 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "freq", "clock class");
4120 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &freq
);
4122 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4123 entry_node
, "Unexpected unary expression for clock class's `freq` attribute.");
4128 if (freq
== UINT64_C(-1) || freq
== 0) {
4129 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Invalid clock class frequency: freq={}",
4135 clock
->frequency
= freq
;
4136 _SET(set
, _CLOCK_FREQ_SET
);
4137 } else if (strcmp(left
, "precision") == 0) {
4140 if (_IS_SET(set
, _CLOCK_PRECISION_SET
)) {
4141 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "precision", "clock class");
4146 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &precision
);
4148 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4149 entry_node
, "Unexpected unary expression for clock class's `precision` attribute.");
4154 clock
->precision
= precision
;
4155 _SET(set
, _CLOCK_PRECISION_SET
);
4156 } else if (strcmp(left
, "offset_s") == 0) {
4157 if (_IS_SET(set
, _CLOCK_OFFSET_S_SET
)) {
4158 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset_s", "clock class");
4163 ret
= get_unary_signed(&entry_node
->u
.ctf_expression
.right
, offset_seconds
);
4165 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4166 entry_node
, "Unexpected unary expression for clock class's `offset_s` attribute.");
4171 _SET(set
, _CLOCK_OFFSET_S_SET
);
4172 } else if (strcmp(left
, "offset") == 0) {
4173 if (_IS_SET(set
, _CLOCK_OFFSET_SET
)) {
4174 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset", "clock class");
4179 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, offset_cycles
);
4181 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4182 entry_node
, "Unexpected unary expression for clock class's `offset` attribute.");
4187 _SET(set
, _CLOCK_OFFSET_SET
);
4188 } else if (strcmp(left
, "absolute") == 0) {
4189 struct ctf_node
*right
;
4191 if (_IS_SET(set
, _CLOCK_ABSOLUTE_SET
)) {
4192 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "absolute", "clock class");
4198 _BT_LIST_FIRST_ENTRY(&entry_node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4199 ret
= get_boolean(ctx
, right
);
4201 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4202 entry_node
, "Unexpected unary expression for clock class's `absolute` attribute.");
4207 clock
->is_absolute
= ret
;
4208 _SET(set
, _CLOCK_ABSOLUTE_SET
);
4210 _BT_CPPLOGW_NODE(entry_node
, "Unknown attribute in clock class: attr-name=\"{}\"", left
);
4222 static inline uint64_t cycles_from_ns(uint64_t frequency
, uint64_t ns
)
4227 if (frequency
== UINT64_C(1000000000)) {
4230 cycles
= (uint64_t) (((double) ns
* (double) frequency
) / 1e9
);
4236 static void calibrate_clock_class_offsets(int64_t *offset_seconds
, uint64_t *offset_cycles
,
4239 if (*offset_cycles
>= freq
) {
4240 const uint64_t s_in_offset_cycles
= *offset_cycles
/ freq
;
4242 *offset_seconds
+= (int64_t) s_in_offset_cycles
;
4243 *offset_cycles
-= (s_in_offset_cycles
* freq
);
4247 static void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir
*ctx
,
4248 struct ctf_clock_class
*clock
)
4250 if (ctx
->decoder_config
.force_clock_class_origin_unix_epoch
) {
4251 clock
->is_absolute
= true;
4257 static void apply_clock_class_offset(struct ctf_visitor_generate_ir
*ctx
,
4258 struct ctf_clock_class
*clock
)
4261 int64_t offset_s_to_apply
= ctx
->decoder_config
.clock_class_offset_s
;
4262 uint64_t offset_ns_to_apply
;
4263 int64_t cur_offset_s
;
4264 uint64_t cur_offset_cycles
;
4266 if (ctx
->decoder_config
.clock_class_offset_s
== 0 &&
4267 ctx
->decoder_config
.clock_class_offset_ns
== 0) {
4271 /* Transfer nanoseconds to seconds as much as possible */
4272 if (ctx
->decoder_config
.clock_class_offset_ns
< 0) {
4273 const int64_t abs_ns
= -ctx
->decoder_config
.clock_class_offset_ns
;
4274 const int64_t abs_extra_s
= abs_ns
/ INT64_C(1000000000) + 1;
4275 const int64_t extra_s
= -abs_extra_s
;
4276 const int64_t offset_ns
=
4277 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4279 BT_ASSERT(offset_ns
> 0);
4280 offset_ns_to_apply
= (uint64_t) offset_ns
;
4281 offset_s_to_apply
+= extra_s
;
4283 const int64_t extra_s
= ctx
->decoder_config
.clock_class_offset_ns
/ INT64_C(1000000000);
4284 const int64_t offset_ns
=
4285 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4287 BT_ASSERT(offset_ns
>= 0);
4288 offset_ns_to_apply
= (uint64_t) offset_ns
;
4289 offset_s_to_apply
+= extra_s
;
4292 freq
= clock
->frequency
;
4293 cur_offset_s
= clock
->offset_seconds
;
4294 cur_offset_cycles
= clock
->offset_cycles
;
4297 cur_offset_s
+= offset_s_to_apply
;
4298 cur_offset_cycles
+= cycles_from_ns(freq
, offset_ns_to_apply
);
4301 * Recalibrate offsets because the part in cycles can be greater
4302 * than the frequency at this point.
4304 calibrate_clock_class_offsets(&cur_offset_s
, &cur_offset_cycles
, freq
);
4306 /* Set final offsets */
4307 clock
->offset_seconds
= cur_offset_s
;
4308 clock
->offset_cycles
= cur_offset_cycles
;
4314 static int visit_clock_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*clock_node
)
4318 struct ctf_clock_class
*clock
;
4319 struct ctf_node
*entry_node
;
4320 struct bt_list_head
*decl_list
= &clock_node
->u
.clock
.declaration_list
;
4321 const char *clock_class_name
;
4322 int64_t offset_seconds
= 0;
4323 uint64_t offset_cycles
= 0;
4326 if (clock_node
->visited
) {
4330 clock_node
->visited
= TRUE
;
4332 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4333 clock
= ctf_clock_class_create();
4335 _BT_CPPLOGE_APPEND_CAUSE_NODE(clock_node
, "Cannot create default clock class.");
4340 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
4341 ret
= visit_clock_decl_entry(ctx
, entry_node
, clock
, &set
, &offset_seconds
, &offset_cycles
);
4343 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot visit clock class's entry: ret={}",
4349 if (!_IS_SET(&set
, _CLOCK_NAME_SET
)) {
4350 _BT_CPPLOGE_APPEND_CAUSE_NODE(clock_node
, "Missing `name` attribute in clock class.");
4355 clock_class_name
= clock
->name
->str
;
4356 BT_ASSERT(clock_class_name
);
4357 if (ctx
->is_lttng
&& strcmp(clock_class_name
, "monotonic") == 0) {
4359 * Old versions of LTTng forgot to set its clock class
4360 * as absolute, even if it is. This is important because
4361 * it's a condition to be able to sort messages
4362 * from different sources.
4364 clock
->is_absolute
= true;
4368 * Adjust offsets so that the part in cycles is less than the
4369 * frequency (move to the part in seconds).
4371 freq
= clock
->frequency
;
4372 calibrate_clock_class_offsets(&offset_seconds
, &offset_cycles
, freq
);
4373 BT_ASSERT(offset_cycles
< clock
->frequency
);
4374 clock
->offset_seconds
= offset_seconds
;
4375 clock
->offset_cycles
= offset_cycles
;
4376 apply_clock_class_offset(ctx
, clock
);
4377 apply_clock_class_is_absolute(ctx
, clock
);
4378 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock
);
4383 ctf_clock_class_destroy(clock
);
4389 static int visit_root_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*root_decl_node
)
4393 if (root_decl_node
->visited
) {
4397 root_decl_node
->visited
= TRUE
;
4399 switch (root_decl_node
->type
) {
4402 visit_field_class_def(ctx
, root_decl_node
->u
.field_class_def
.field_class_specifier_list
,
4403 &root_decl_node
->u
.field_class_def
.field_class_declarators
);
4405 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node
,
4406 "Cannot add field class found in root scope.");
4410 case NODE_TYPEALIAS
:
4411 ret
= visit_field_class_alias(ctx
, root_decl_node
->u
.field_class_alias
.target
,
4412 root_decl_node
->u
.field_class_alias
.alias
);
4414 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node
,
4415 "Cannot add field class alias found in root scope.");
4419 case NODE_TYPE_SPECIFIER_LIST
:
4421 struct ctf_field_class
*decl
= NULL
;
4424 * Just add the field class specifier to the root
4425 * declaration scope. Put local reference.
4427 ret
= visit_field_class_specifier_list(ctx
, root_decl_node
, &decl
);
4429 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node
,
4430 "Cannot visit root scope's field class: "
4437 ctf_field_class_destroy(decl
);
4442 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node
, "Unexpected node type: node-type={}",
4443 root_decl_node
->type
);
4452 struct ctf_visitor_generate_ir
*
4453 ctf_visitor_generate_ir_create(const struct ctf_metadata_decoder_config
*decoder_config
)
4455 struct ctf_visitor_generate_ir
*ctx
= NULL
;
4457 bt2c::Logger logger
{decoder_config
->logger
, "PLUGIN/CTF/META/IR-VISITOR"};
4459 /* Create visitor's context */
4460 ctx
= ctx_create(decoder_config
, logger
);
4462 BT_CPPLOGE_APPEND_CAUSE_SPEC(logger
, "Cannot create visitor's context.");
4476 void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir
*visitor
)
4478 ctx_destroy(visitor
);
4481 bt_trace_class
*ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4485 if (ctx
->trace_class
) {
4486 bt_trace_class_get_ref(ctx
->trace_class
);
4489 return ctx
->trace_class
;
4492 struct ctf_trace_class
*
4493 ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4496 BT_ASSERT_DBG(ctx
->ctf_tc
);
4500 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
4504 BT_CPPLOGI_STR_SPEC(ctx
->logger
, "Visiting metadata's AST to generate CTF IR objects.");
4506 switch (node
->type
) {
4509 struct ctf_node
*iter
;
4510 bool got_trace_decl
= false;
4513 * The first thing we need is the native byte order of
4514 * the trace block, because early class aliases can have
4515 * a `byte_order` attribute set to `native`. If we don't
4516 * have the native byte order yet, and we don't have any
4517 * trace block yet, then fail with EINCOMPLETE.
4519 if (ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
4520 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4521 if (got_trace_decl
) {
4522 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
4527 ret
= set_trace_byte_order(ctx
, iter
);
4529 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
4530 "Cannot set trace's native byte order: "
4536 got_trace_decl
= true;
4539 if (!got_trace_decl
) {
4540 BT_CPPLOGD_STR_SPEC(ctx
->logger
, "Incomplete AST: need trace (`trace` block).");
4546 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_LITTLE
||
4547 ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_BIG
);
4548 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4551 bt_list_for_each_entry (iter
, &node
->u
.root
.env
, siblings
) {
4552 ret
= visit_env(ctx
, iter
);
4554 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4556 "Cannot visit trace's environment (`env` block) entry: "
4563 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4566 * Visit clock blocks.
4568 bt_list_for_each_entry (iter
, &node
->u
.root
.clock
, siblings
) {
4569 ret
= visit_clock_decl(ctx
, iter
);
4571 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit clock class: ret={}", ret
);
4576 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4579 * Visit root declarations next, as they can be used by any
4582 bt_list_for_each_entry (iter
, &node
->u
.root
.declaration_list
, siblings
) {
4583 ret
= visit_root_decl(ctx
, iter
);
4585 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit root entry: ret={}", ret
);
4590 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4592 /* Callsite blocks are not supported */
4593 bt_list_for_each_entry (iter
, &node
->u
.root
.callsite
, siblings
) {
4594 _BT_CPPLOGW_NODE(iter
, "\"callsite\" blocks are not supported as of this version.");
4597 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4600 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4601 ret
= visit_trace_decl(ctx
, iter
);
4603 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
4604 "Cannot visit trace (`trace` block): "
4611 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4614 bt_list_for_each_entry (iter
, &node
->u
.root
.stream
, siblings
) {
4615 ret
= visit_stream_decl(ctx
, iter
);
4617 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit stream class: ret={}", ret
);
4622 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4625 bt_list_for_each_entry (iter
, &node
->u
.root
.event
, siblings
) {
4626 ret
= visit_event_decl(ctx
, iter
);
4628 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit event class: ret={}", ret
);
4633 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4637 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Unexpected node type: node-type={}", node
->type
);
4642 /* Update default clock classes */
4643 ret
= ctf_trace_class_update_default_clock_classes(ctx
->ctf_tc
, ctx
->logger
);
4649 /* Update trace class meanings */
4650 ret
= ctf_trace_class_update_meanings(ctx
->ctf_tc
);
4656 /* Update stream class configuration */
4657 ret
= ctf_trace_class_update_stream_class_config(ctx
->ctf_tc
);
4663 /* Update text arrays and sequences */
4664 ret
= ctf_trace_class_update_text_array_sequence(ctx
->ctf_tc
);
4670 /* Update structure/array/sequence alignments */
4671 ret
= ctf_trace_class_update_alignments(ctx
->ctf_tc
);
4677 /* Resolve sequence lengths and variant tags */
4678 ret
= ctf_trace_class_resolve_field_classes(ctx
->ctf_tc
, ctx
->logger
);
4684 if (ctx
->trace_class
) {
4686 * Update "in IR" for field classes.
4688 * If we have no IR trace class, then we'll have no way
4689 * to create IR fields anyway, so we leave all the
4690 * `in_ir` members false.
4692 ret
= ctf_trace_class_update_in_ir(ctx
->ctf_tc
);
4699 /* Update saved value indexes */
4700 ret
= ctf_trace_class_update_value_storing_indexes(ctx
->ctf_tc
);
4706 /* Validate what we have so far */
4707 ret
= ctf_trace_class_validate(ctx
->ctf_tc
, ctx
->logger
);
4714 * If there are fields which are not related to the CTF format
4715 * itself in the packet header and in event header field
4716 * classes, warn about it because they are never translated.
4718 ctf_trace_class_warn_meaningless_header_fields(ctx
->ctf_tc
, ctx
->logger
);
4720 if (ctx
->trace_class
) {
4721 /* Copy new CTF metadata -> new IR metadata */
4723 ctf_trace_class_translate(ctx
->decoder_config
.self_comp
, ctx
->trace_class
, ctx
->ctf_tc
);