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 * Creates a new declaration scope.
174 * @param par_scope Parent scope (NULL if creating a root scope)
175 * @returns New declaration scope, or NULL on error
177 static struct ctx_decl_scope
*ctx_decl_scope_create(struct ctf_visitor_generate_ir
*ctx
,
178 struct ctx_decl_scope
*par_scope
)
180 struct ctx_decl_scope
*scope
;
182 scope
= g_new(struct ctx_decl_scope
, 1);
184 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Failed to allocate one declaration scope.");
188 scope
->decl_map
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
,
189 (GDestroyNotify
) ctf_field_class_destroy
);
190 scope
->parent_scope
= par_scope
;
197 * Destroys a declaration scope.
199 * This function does not destroy the parent scope.
201 * @param scope Scope to destroy
203 static void ctx_decl_scope_destroy(struct ctx_decl_scope
*scope
)
209 g_hash_table_destroy(scope
->decl_map
);
217 * Returns the GQuark of a prefixed alias.
219 * @param prefix Prefix character
221 * @returns Associated GQuark, or 0 on error
223 static GQuark
get_prefixed_named_quark(char prefix
, const char *name
)
226 std::string prname
= std::string
{prefix
} + name
;
227 return g_quark_from_string(prname
.c_str());
231 * Looks up a prefixed class alias within a declaration scope.
233 * @param scope Declaration scope
234 * @param prefix Prefix character
235 * @param name Alias name
236 * @param levels Number of levels to dig into (-1 means infinite)
237 * @param copy True to return a copy
238 * @returns Declaration (owned by caller if \p copy is true),
239 * or NULL if not found
241 static struct ctf_field_class
*ctx_decl_scope_lookup_prefix_alias(struct ctx_decl_scope
*scope
,
242 char prefix
, const char *name
,
243 int levels
, bool copy
)
247 struct ctf_field_class
*decl
= NULL
;
248 struct ctx_decl_scope
*cur_scope
= scope
;
252 qname
= get_prefixed_named_quark(prefix
, name
);
261 while (cur_scope
&& cur_levels
< levels
) {
262 decl
= (ctf_field_class
*) g_hash_table_lookup(cur_scope
->decl_map
,
263 (gconstpointer
) GUINT_TO_POINTER(qname
));
265 /* Caller's reference */
267 decl
= ctf_field_class_copy(decl
);
274 cur_scope
= cur_scope
->parent_scope
;
283 * Looks up a class alias within a declaration scope.
285 * @param scope Declaration scope
286 * @param name Alias name
287 * @param levels Number of levels to dig into (-1 means infinite)
288 * @param copy True to return a copy
289 * @returns Declaration (owned by caller if \p copy is true),
290 * or NULL if not found
292 static struct ctf_field_class
*ctx_decl_scope_lookup_alias(struct ctx_decl_scope
*scope
,
293 const char *name
, int levels
, bool copy
)
295 return ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ALIAS
, name
, levels
, copy
);
299 * Looks up an enumeration within a declaration scope.
301 * @param scope Declaration scope
302 * @param name Enumeration name
303 * @param levels Number of levels to dig into (-1 means infinite)
304 * @param copy True to return a copy
305 * @returns Declaration (owned by caller if \p copy is true),
306 * or NULL if not found
308 static struct ctf_field_class_enum
*
309 ctx_decl_scope_lookup_enum(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
311 return ctf_field_class_as_enum(
312 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ENUM
, name
, levels
, copy
));
316 * Looks up a structure within a declaration scope.
318 * @param scope Declaration scope
319 * @param name Structure name
320 * @param levels Number of levels to dig into (-1 means infinite)
321 * @param copy True to return a copy
322 * @returns Declaration (owned by caller if \p copy is true),
323 * or NULL if not found
325 static struct ctf_field_class_struct
*
326 ctx_decl_scope_lookup_struct(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
328 return ctf_field_class_as_struct(
329 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_STRUCT
, name
, levels
, copy
));
333 * Looks up a variant within a declaration scope.
335 * @param scope Declaration scope
336 * @param name Variant name
337 * @param levels Number of levels to dig into (-1 means infinite)
338 * @param copy True to return a copy
339 * @returns Declaration (owned by caller if \p copy is true),
340 * or NULL if not found
342 static struct ctf_field_class_variant
*
343 ctx_decl_scope_lookup_variant(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
345 return ctf_field_class_as_variant(
346 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_VARIANT
, name
, levels
, copy
));
350 * Registers a prefixed class alias within a declaration scope.
352 * @param scope Declaration scope
353 * @param prefix Prefix character
354 * @param name Alias name (non-NULL)
355 * @param decl Field class to register (copied)
356 * @returns 0 if registration went okay, negative value otherwise
358 static int ctx_decl_scope_register_prefix_alias(struct ctx_decl_scope
*scope
, char prefix
,
359 const char *name
, struct ctf_field_class
*decl
)
367 qname
= get_prefixed_named_quark(prefix
, name
);
373 /* Make sure alias does not exist in local scope */
374 if (ctx_decl_scope_lookup_prefix_alias(scope
, prefix
, name
, 1, false)) {
379 decl
= ctf_field_class_copy(decl
);
381 g_hash_table_insert(scope
->decl_map
, GUINT_TO_POINTER(qname
), decl
);
388 * Registers a class alias within a declaration scope.
390 * @param scope Declaration scope
391 * @param name Alias name (non-NULL)
392 * @param decl Field class to register (copied)
393 * @returns 0 if registration went okay, negative value otherwise
395 static int ctx_decl_scope_register_alias(struct ctx_decl_scope
*scope
, const char *name
,
396 struct ctf_field_class
*decl
)
398 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ALIAS
, name
, decl
);
402 * Registers an enumeration declaration within a declaration scope.
404 * @param scope Declaration scope
405 * @param name Enumeration name (non-NULL)
406 * @param decl Enumeration field class to register (copied)
407 * @returns 0 if registration went okay, negative value otherwise
409 static int ctx_decl_scope_register_enum(struct ctx_decl_scope
*scope
, const char *name
,
410 struct ctf_field_class_enum
*decl
)
412 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ENUM
, name
, &decl
->base
.base
.base
);
416 * Registers a structure declaration within a declaration scope.
418 * @param scope Declaration scope
419 * @param name Structure name (non-NULL)
420 * @param decl Structure field class to register (copied)
421 * @returns 0 if registration went okay, negative value otherwise
423 static int ctx_decl_scope_register_struct(struct ctx_decl_scope
*scope
, const char *name
,
424 struct ctf_field_class_struct
*decl
)
426 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_STRUCT
, name
, &decl
->base
);
430 * Registers a variant declaration within a declaration scope.
432 * @param scope Declaration scope
433 * @param name Variant name (non-NULL)
434 * @param decl Variant field class to register
435 * @returns 0 if registration went okay, negative value otherwise
437 static int ctx_decl_scope_register_variant(struct ctx_decl_scope
*scope
, const char *name
,
438 struct ctf_field_class_variant
*decl
)
440 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_VARIANT
, name
, &decl
->base
);
444 * Destroys a visitor context.
446 * @param ctx Visitor context to destroy
448 static void ctx_destroy(struct ctf_visitor_generate_ir
*ctx
)
450 struct ctx_decl_scope
*scope
;
456 scope
= ctx
->current_scope
;
459 * Destroy all scopes, from current one to the root scope.
462 struct ctx_decl_scope
*parent_scope
= scope
->parent_scope
;
464 ctx_decl_scope_destroy(scope
);
465 scope
= parent_scope
;
468 bt_trace_class_put_ref(ctx
->trace_class
);
471 ctf_trace_class_destroy(ctx
->ctf_tc
);
481 * Creates a new visitor context.
483 * @param trace Associated trace
484 * @returns New visitor context, or NULL on error
486 static ctf_visitor_generate_ir::UP
487 ctx_create(const struct ctf_metadata_decoder_config
*decoder_config
, const bt2c::Logger
& logger
)
489 BT_ASSERT(decoder_config
);
491 ctf_visitor_generate_ir::UP ctx
{new ctf_visitor_generate_ir
{*decoder_config
, logger
}};
493 if (decoder_config
->self_comp
) {
494 ctx
->trace_class
= bt_trace_class_create(decoder_config
->self_comp
);
495 if (!ctx
->trace_class
) {
496 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Cannot create empty trace class.");
501 ctx
->ctf_tc
= ctf_trace_class_create();
503 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Cannot create CTF trace class.");
507 /* Root declaration scope */
508 ctx
->current_scope
= ctx_decl_scope_create(ctx
.get(), NULL
);
509 if (!ctx
->current_scope
) {
510 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Cannot create declaration scope.");
524 * Pushes a new declaration scope on top of a visitor context's
525 * declaration scope stack.
527 * @param ctx Visitor context
528 * @returns 0 on success, or a negative value on error
530 static int ctx_push_scope(struct ctf_visitor_generate_ir
*ctx
)
533 struct ctx_decl_scope
*new_scope
;
536 new_scope
= ctx_decl_scope_create(ctx
, ctx
->current_scope
);
538 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Cannot create declaration scope.");
543 ctx
->current_scope
= new_scope
;
549 static void ctx_pop_scope(struct ctf_visitor_generate_ir
*ctx
)
551 struct ctx_decl_scope
*parent_scope
= NULL
;
555 if (!ctx
->current_scope
) {
559 parent_scope
= ctx
->current_scope
->parent_scope
;
560 ctx_decl_scope_destroy(ctx
->current_scope
);
561 ctx
->current_scope
= parent_scope
;
567 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
568 struct ctf_node
*ts_list
,
569 struct ctf_field_class
**decl
);
571 static int is_unary_string(struct bt_list_head
*head
)
574 struct ctf_node
*node
;
576 bt_list_for_each_entry (node
, head
, siblings
) {
577 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
581 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
589 static const char *get_map_clock_name_value(struct bt_list_head
*head
)
592 struct ctf_node
*node
;
593 const char *name
= NULL
;
595 bt_list_for_each_entry (node
, head
, siblings
) {
597 int uexpr_type
= node
->u
.unary_expression
.type
;
598 int uexpr_link
= node
->u
.unary_expression
.link
;
599 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_STRING
||
600 !((uexpr_link
!= UNARY_LINK_UNKNOWN
) ^ (i
== 0));
605 /* Needs to be chained with . */
606 switch (node
->u
.unary_expression
.link
) {
609 case UNARY_ARROWLINK
:
610 case UNARY_DOTDOTDOT
:
616 src_string
= node
->u
.unary_expression
.u
.string
;
620 if (strcmp("clock", src_string
)) {
628 if (strcmp("value", src_string
)) {
633 /* Extra identifier, unknown */
646 static int is_unary_unsigned(struct bt_list_head
*head
)
649 struct ctf_node
*node
;
651 bt_list_for_each_entry (node
, head
, siblings
) {
652 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
656 if (node
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
664 static int get_unary_unsigned(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
669 struct ctf_node
*node
;
673 if (bt_list_empty(head
)) {
678 bt_list_for_each_entry (node
, head
, siblings
) {
679 int uexpr_type
= node
->u
.unary_expression
.type
;
680 int uexpr_link
= node
->u
.unary_expression
.link
;
681 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_UNSIGNED_CONSTANT
||
682 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
684 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Invalid constant unsigned integer.");
689 *value
= node
->u
.unary_expression
.u
.unsigned_constant
;
697 static int is_unary_signed(struct bt_list_head
*head
)
700 struct ctf_node
*node
;
702 bt_list_for_each_entry (node
, head
, siblings
) {
703 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
707 if (node
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
) {
715 static int get_unary_signed(struct bt_list_head
*head
, int64_t *value
)
719 struct ctf_node
*node
;
721 bt_list_for_each_entry (node
, head
, siblings
) {
722 int uexpr_type
= node
->u
.unary_expression
.type
;
723 int uexpr_link
= node
->u
.unary_expression
.link
;
724 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
725 (uexpr_type
!= UNARY_UNSIGNED_CONSTANT
&& uexpr_type
!= UNARY_SIGNED_CONSTANT
) ||
726 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
732 switch (uexpr_type
) {
733 case UNARY_UNSIGNED_CONSTANT
:
734 *value
= (int64_t) node
->u
.unary_expression
.u
.unsigned_constant
;
736 case UNARY_SIGNED_CONSTANT
:
737 *value
= node
->u
.unary_expression
.u
.signed_constant
;
751 static int get_unary_uuid(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
754 return ctf_ast_get_unary_uuid(head
, uuid
, ctx
->logger
);
757 static int get_boolean(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*unary_expr
)
761 if (unary_expr
->type
!= NODE_UNARY_EXPRESSION
) {
762 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr
, "Expecting unary expression: node-type={}",
768 switch (unary_expr
->u
.unary_expression
.type
) {
769 case UNARY_UNSIGNED_CONSTANT
:
770 ret
= (unary_expr
->u
.unary_expression
.u
.unsigned_constant
!= 0);
772 case UNARY_SIGNED_CONSTANT
:
773 ret
= (unary_expr
->u
.unary_expression
.u
.signed_constant
!= 0);
777 const char *str
= unary_expr
->u
.unary_expression
.u
.string
;
779 if (strcmp(str
, "true") == 0 || strcmp(str
, "TRUE") == 0) {
781 } else if (strcmp(str
, "false") == 0 || strcmp(str
, "FALSE") == 0) {
784 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr
, "Unexpected boolean value: value=\"{}\"",
792 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr
, "Unexpected unary expression type: node-type={}",
793 unary_expr
->u
.unary_expression
.type
);
802 static enum ctf_byte_order
byte_order_from_unary_expr(struct ctf_visitor_generate_ir
*ctx
,
803 struct ctf_node
*unary_expr
)
806 enum ctf_byte_order bo
= CTF_BYTE_ORDER_UNKNOWN
;
808 if (unary_expr
->u
.unary_expression
.type
!= UNARY_STRING
) {
809 _BT_CPPLOGE_APPEND_CAUSE_NODE(
810 unary_expr
, "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
814 str
= unary_expr
->u
.unary_expression
.u
.string
;
816 if (strcmp(str
, "be") == 0 || strcmp(str
, "network") == 0) {
817 bo
= CTF_BYTE_ORDER_BIG
;
818 } else if (strcmp(str
, "le") == 0) {
819 bo
= CTF_BYTE_ORDER_LITTLE
;
820 } else if (strcmp(str
, "native") == 0) {
821 bo
= CTF_BYTE_ORDER_DEFAULT
;
823 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr
,
824 "Unexpected \"byte_order\" attribute value: "
825 "expecting `be`, `le`, `network`, or `native`: value=\"{}\"",
834 static enum ctf_byte_order
get_real_byte_order(struct ctf_visitor_generate_ir
*ctx
,
835 struct ctf_node
*uexpr
)
837 enum ctf_byte_order bo
= byte_order_from_unary_expr(ctx
, uexpr
);
839 if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
840 bo
= ctx
->ctf_tc
->default_byte_order
;
846 static int is_align_valid(uint64_t align
)
848 return (align
!= 0) && !(align
& (align
- UINT64_C(1)));
851 static int get_class_specifier_name(struct ctf_visitor_generate_ir
*ctx
,
852 struct ctf_node
*cls_specifier
, GString
*str
)
856 if (cls_specifier
->type
!= NODE_TYPE_SPECIFIER
) {
857 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier
, "Unexpected node type: node-type={}",
858 cls_specifier
->type
);
863 switch (cls_specifier
->u
.field_class_specifier
.type
) {
865 g_string_append(str
, "void");
868 g_string_append(str
, "char");
871 g_string_append(str
, "short");
874 g_string_append(str
, "int");
877 g_string_append(str
, "long");
880 g_string_append(str
, "float");
882 case TYPESPEC_DOUBLE
:
883 g_string_append(str
, "double");
885 case TYPESPEC_SIGNED
:
886 g_string_append(str
, "signed");
888 case TYPESPEC_UNSIGNED
:
889 g_string_append(str
, "unsigned");
892 g_string_append(str
, "bool");
894 case TYPESPEC_COMPLEX
:
895 g_string_append(str
, "_Complex");
897 case TYPESPEC_IMAGINARY
:
898 g_string_append(str
, "_Imaginary");
901 g_string_append(str
, "const");
903 case TYPESPEC_ID_TYPE
:
904 if (cls_specifier
->u
.field_class_specifier
.id_type
) {
905 g_string_append(str
, cls_specifier
->u
.field_class_specifier
.id_type
);
908 case TYPESPEC_STRUCT
:
910 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
912 if (!node
->u
._struct
.name
) {
913 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty structure field class name.");
918 g_string_append(str
, "struct ");
919 g_string_append(str
, node
->u
._struct
.name
);
922 case TYPESPEC_VARIANT
:
924 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
926 if (!node
->u
.variant
.name
) {
927 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty variant field class name.");
932 g_string_append(str
, "variant ");
933 g_string_append(str
, node
->u
.variant
.name
);
938 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
940 if (!node
->u
._enum
.enum_id
) {
941 _BT_CPPLOGE_APPEND_CAUSE_NODE(
942 node
, "Unexpected empty enumeration field class (`enum`) name.");
947 g_string_append(str
, "enum ");
948 g_string_append(str
, node
->u
._enum
.enum_id
);
951 case TYPESPEC_FLOATING_POINT
:
952 case TYPESPEC_INTEGER
:
953 case TYPESPEC_STRING
:
955 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier
->u
.field_class_specifier
.node
,
956 "Unexpected field class specifier type: {}",
957 cls_specifier
->u
.field_class_specifier
.type
);
966 static int get_class_specifier_list_name(struct ctf_visitor_generate_ir
*ctx
,
967 struct ctf_node
*cls_specifier_list
, GString
*str
)
970 struct ctf_node
*iter
;
971 int alias_item_nr
= 0;
972 struct bt_list_head
*head
= &cls_specifier_list
->u
.field_class_specifier_list
.head
;
974 bt_list_for_each_entry (iter
, head
, siblings
) {
975 if (alias_item_nr
!= 0) {
976 g_string_append(str
, " ");
980 ret
= get_class_specifier_name(ctx
, iter
, str
);
990 static GQuark
create_class_alias_identifier(struct ctf_visitor_generate_ir
*ctx
,
991 struct ctf_node
*cls_specifier_list
,
992 struct ctf_node
*node_field_class_declarator
)
998 struct ctf_node
*iter
;
999 struct bt_list_head
*pointers
= &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1001 str
= g_string_new("");
1002 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
1004 g_string_free(str
, TRUE
);
1008 bt_list_for_each_entry (iter
, pointers
, siblings
) {
1009 g_string_append(str
, " *");
1011 if (iter
->u
.pointer
.const_qualifier
) {
1012 g_string_append(str
, " const");
1016 str_c
= g_string_free(str
, FALSE
);
1017 qalias
= g_quark_from_string(str_c
);
1024 static int visit_field_class_declarator(struct ctf_visitor_generate_ir
*ctx
,
1025 struct ctf_node
*cls_specifier_list
, GQuark
*field_name
,
1026 struct ctf_node
*node_field_class_declarator
,
1027 struct ctf_field_class
**field_decl
,
1028 struct ctf_field_class
*nested_decl
)
1031 * During this whole function, nested_decl is always OURS,
1032 * whereas field_decl is an output which we create, but
1033 * belongs to the caller (it is moved).
1038 /* Validate field class declarator node */
1039 if (node_field_class_declarator
) {
1040 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_UNKNOWN
) {
1041 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1042 node_field_class_declarator
, "Unexpected field class declarator type: type={}",
1043 node_field_class_declarator
->u
.field_class_declarator
.type
);
1048 /* TODO: GCC bitfields not supported yet */
1049 if (node_field_class_declarator
->u
.field_class_declarator
.bitfield_len
!= NULL
) {
1050 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1051 "GCC bitfields are not supported as of this version.");
1057 /* Find the right nested declaration if not provided */
1059 if (node_field_class_declarator
&&
1060 !bt_list_empty(&node_field_class_declarator
->u
.field_class_declarator
.pointers
)) {
1064 * If we have a pointer declarator, it HAS to
1065 * be present in the field class aliases (else
1069 create_class_alias_identifier(ctx
, cls_specifier_list
, node_field_class_declarator
);
1070 nested_decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, g_quark_to_string(qalias
),
1073 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1074 "Cannot find class alias: name=\"{}\"",
1075 g_quark_to_string(qalias
));
1080 if (nested_decl
->type
== CTF_FIELD_CLASS_TYPE_INT
) {
1081 /* Pointer: force integer's base to 16 */
1082 struct ctf_field_class_int
*int_fc
= ctf_field_class_as_int(nested_decl
);
1084 int_fc
->disp_base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
1087 ret
= visit_field_class_specifier_list(ctx
, cls_specifier_list
, &nested_decl
);
1089 BT_ASSERT(!nested_decl
);
1095 BT_ASSERT(nested_decl
);
1097 if (!node_field_class_declarator
) {
1098 *field_decl
= nested_decl
;
1103 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_ID
) {
1104 if (node_field_class_declarator
->u
.field_class_declarator
.u
.id
) {
1105 const char *id
= node_field_class_declarator
->u
.field_class_declarator
.u
.id
;
1107 *field_name
= g_quark_from_string(id
);
1112 *field_decl
= nested_decl
;
1116 struct ctf_node
*first
;
1117 struct ctf_field_class
*decl
= NULL
;
1118 struct ctf_field_class
*outer_field_decl
= NULL
;
1119 struct bt_list_head
*length
=
1120 &node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.length
;
1122 /* Create array/sequence, pass nested_decl as child */
1123 if (bt_list_empty(length
)) {
1124 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1125 "Expecting length field reference or value.");
1130 first
= _BT_LIST_FIRST_ENTRY(length
, struct ctf_node
, siblings
);
1131 if (first
->type
!= NODE_UNARY_EXPRESSION
) {
1132 _BT_CPPLOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type={}", first
->type
);
1137 switch (first
->u
.unary_expression
.type
) {
1138 case UNARY_UNSIGNED_CONSTANT
:
1140 struct ctf_field_class_array
*array_decl
= NULL
;
1142 array_decl
= ctf_field_class_array_create();
1143 BT_ASSERT(array_decl
);
1144 array_decl
->length
= first
->u
.unary_expression
.u
.unsigned_constant
;
1145 array_decl
->base
.elem_fc
= nested_decl
;
1147 decl
= &array_decl
->base
.base
;
1152 /* Lookup unsigned integer definition, create seq. */
1153 struct ctf_field_class_sequence
*seq_decl
= NULL
;
1154 char *length_name
= ctf_ast_concatenate_unary_strings(length
);
1157 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1158 "Cannot concatenate unary strings.");
1163 if (strncmp(length_name
, "env.", 4) == 0) {
1164 /* This is, in fact, an array */
1165 const char *env_entry_name
= &length_name
[4];
1166 struct ctf_trace_class_env_entry
*env_entry
=
1167 ctf_trace_class_borrow_env_entry_by_name(ctx
->ctf_tc
, env_entry_name
);
1168 struct ctf_field_class_array
*array_decl
;
1171 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1172 "Cannot find environment entry: "
1179 if (env_entry
->type
!= CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
) {
1180 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1181 "Wrong environment entry type "
1182 "(expecting integer): "
1189 if (env_entry
->value
.i
< 0) {
1190 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1191 "Invalid, negative array length: "
1192 "env-entry-name=\"{}\", "
1194 env_entry_name
, env_entry
->value
.i
);
1199 array_decl
= ctf_field_class_array_create();
1200 BT_ASSERT(array_decl
);
1201 array_decl
->length
= (uint64_t) env_entry
->value
.i
;
1202 array_decl
->base
.elem_fc
= nested_decl
;
1204 decl
= &array_decl
->base
.base
;
1206 seq_decl
= ctf_field_class_sequence_create();
1207 BT_ASSERT(seq_decl
);
1208 seq_decl
->base
.elem_fc
= nested_decl
;
1210 g_string_assign(seq_decl
->length_ref
, length_name
);
1211 decl
= &seq_decl
->base
.base
;
1214 g_free(length_name
);
1222 BT_ASSERT(!nested_decl
);
1224 BT_ASSERT(!*field_decl
);
1227 * At this point, we found the next nested declaration.
1228 * We currently own this (and lost the ownership of
1229 * nested_decl in the meantime). Pass this next
1230 * nested declaration as the content of the outer
1231 * container, MOVING its ownership.
1233 ret
= visit_field_class_declarator(
1234 ctx
, cls_specifier_list
, field_name
,
1235 node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.field_class_declarator
,
1236 &outer_field_decl
, decl
);
1239 BT_ASSERT(!outer_field_decl
);
1244 BT_ASSERT(outer_field_decl
);
1245 *field_decl
= outer_field_decl
;
1246 outer_field_decl
= NULL
;
1249 BT_ASSERT(*field_decl
);
1253 ctf_field_class_destroy(*field_decl
);
1261 ctf_field_class_destroy(nested_decl
);
1266 static int visit_struct_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1267 struct ctf_field_class_struct
*struct_decl
,
1268 struct ctf_node
*cls_specifier_list
,
1269 struct bt_list_head
*field_class_declarators
)
1272 struct ctf_node
*iter
;
1273 struct ctf_field_class
*field_decl
= NULL
;
1275 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1278 const char *field_name
;
1280 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1283 BT_ASSERT(!field_decl
);
1284 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1285 "Cannot visit field class declarator: ret={}", ret
);
1289 BT_ASSERT(field_decl
);
1290 field_name
= g_quark_to_string(qfield_name
);
1292 /* Check if field with same name already exists */
1293 if (ctf_field_class_struct_borrow_member_by_name(struct_decl
, field_name
)) {
1294 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1295 "Duplicate field in structure field class: "
1296 "field-name=\"{}\"",
1302 /* Add field to structure */
1303 ctf_field_class_struct_append_member(struct_decl
, field_name
, field_decl
);
1310 ctf_field_class_destroy(field_decl
);
1315 static int visit_variant_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1316 struct ctf_field_class_variant
*variant_decl
,
1317 struct ctf_node
*cls_specifier_list
,
1318 struct bt_list_head
*field_class_declarators
)
1321 struct ctf_node
*iter
;
1322 struct ctf_field_class
*field_decl
= NULL
;
1324 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1327 const char *field_name
;
1329 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1332 BT_ASSERT(!field_decl
);
1333 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1334 "Cannot visit field class declarator: ret={}", ret
);
1338 BT_ASSERT(field_decl
);
1339 field_name
= g_quark_to_string(qfield_name
);
1341 /* Check if field with same name already exists */
1342 if (ctf_field_class_variant_borrow_option_by_name(variant_decl
, field_name
)) {
1343 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1344 "Duplicate field in variant field class: "
1345 "field-name=\"{}\"",
1351 /* Add field to structure */
1352 ctf_field_class_variant_append_option(variant_decl
, field_name
, field_decl
);
1359 ctf_field_class_destroy(field_decl
);
1364 static int visit_field_class_def(struct ctf_visitor_generate_ir
*ctx
,
1365 struct ctf_node
*cls_specifier_list
,
1366 struct bt_list_head
*field_class_declarators
)
1370 struct ctf_node
*iter
;
1371 struct ctf_field_class
*class_decl
= NULL
;
1373 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1374 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qidentifier
, iter
, &class_decl
,
1377 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit field class declarator: ret={}", ret
);
1382 /* Do not allow field class def and alias of untagged variants */
1383 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1384 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1386 if (var_fc
->tag_path
.path
->len
== 0) {
1387 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1388 iter
, "Type definition of untagged variant field class is not allowed.");
1394 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qidentifier
),
1397 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot register field class alias: name=\"{}\"",
1398 g_quark_to_string(qidentifier
));
1404 ctf_field_class_destroy(class_decl
);
1409 static int visit_field_class_alias(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*target
,
1410 struct ctf_node
*alias
)
1414 struct ctf_node
*node
;
1415 GQuark qdummy_field_name
;
1416 struct ctf_field_class
*class_decl
= NULL
;
1418 /* Create target field class */
1419 if (bt_list_empty(&target
->u
.field_class_alias_target
.field_class_declarators
)) {
1422 node
= _BT_LIST_FIRST_ENTRY(&target
->u
.field_class_alias_target
.field_class_declarators
,
1423 struct ctf_node
, siblings
);
1426 ret
= visit_field_class_declarator(
1427 ctx
, target
->u
.field_class_alias_target
.field_class_specifier_list
, &qdummy_field_name
,
1428 node
, &class_decl
, NULL
);
1430 BT_ASSERT(!class_decl
);
1431 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot visit field class declarator: ret={}", ret
);
1435 /* Do not allow field class def and alias of untagged variants */
1436 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1437 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1439 if (var_fc
->tag_path
.path
->len
== 0) {
1440 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1441 target
, "Type definition of untagged variant field class is not allowed.");
1448 * The semantic validator does not check whether the target is
1449 * abstract or not (if it has an identifier). Check it here.
1451 if (qdummy_field_name
!= 0) {
1452 _BT_CPPLOGE_APPEND_CAUSE_NODE(target
, "Expecting empty identifier: id=\"{}\"",
1453 g_quark_to_string(qdummy_field_name
));
1458 /* Create alias identifier */
1459 node
= _BT_LIST_FIRST_ENTRY(&alias
->u
.field_class_alias_name
.field_class_declarators
,
1460 struct ctf_node
, siblings
);
1461 qalias
= create_class_alias_identifier(
1462 ctx
, alias
->u
.field_class_alias_name
.field_class_specifier_list
, node
);
1463 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qalias
), class_decl
);
1465 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot register class alias: name=\"{}\"",
1466 g_quark_to_string(qalias
));
1471 ctf_field_class_destroy(class_decl
);
1476 static int visit_struct_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
1477 struct ctf_field_class_struct
*struct_decl
)
1481 switch (entry_node
->type
) {
1483 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1484 &entry_node
->u
.field_class_def
.field_class_declarators
);
1486 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1487 entry_node
, "Cannot add field class found in structure field class: ret={}", ret
);
1491 case NODE_TYPEALIAS
:
1492 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1493 entry_node
->u
.field_class_alias
.alias
);
1495 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1496 entry_node
, "Cannot add field class alias found in structure field class: ret={}",
1501 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1503 ret
= visit_struct_decl_field(
1505 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1506 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1512 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type={}",
1522 static int visit_variant_decl_entry(struct ctf_visitor_generate_ir
*ctx
,
1523 struct ctf_node
*entry_node
,
1524 struct ctf_field_class_variant
*variant_decl
)
1528 switch (entry_node
->type
) {
1530 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1531 &entry_node
->u
.field_class_def
.field_class_declarators
);
1533 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1534 entry_node
, "Cannot add field class found in variant field class: ret={}", ret
);
1538 case NODE_TYPEALIAS
:
1539 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1540 entry_node
->u
.field_class_alias
.alias
);
1542 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1543 entry_node
, "Cannot add field class alias found in variant field class: ret={}",
1548 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1550 ret
= visit_variant_decl_field(
1552 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1553 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1559 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type={}",
1569 static int visit_struct_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1570 struct bt_list_head
*decl_list
, int has_body
,
1571 struct bt_list_head
*min_align
,
1572 struct ctf_field_class_struct
**struct_decl
)
1576 BT_ASSERT(struct_decl
);
1577 *struct_decl
= NULL
;
1579 /* For named struct (without body), lookup in declaration scope */
1582 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1583 "Bodyless structure field class: missing name.");
1588 *struct_decl
= ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, -1, true);
1589 if (!*struct_decl
) {
1590 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1591 ctx
->logger
, "Cannot find structure field class: name=\"struct {}\"", name
);
1596 struct ctf_node
*entry_node
;
1597 uint64_t min_align_value
= 0;
1600 if (ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, 1, false)) {
1601 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1603 "Structure field class already declared in local scope: "
1604 "name=\"struct {}\"",
1611 if (!bt_list_empty(min_align
)) {
1612 ret
= get_unary_unsigned(ctx
, min_align
, &min_align_value
);
1614 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1616 "Unexpected unary expression for structure field class's `align` attribute: "
1623 *struct_decl
= ctf_field_class_struct_create();
1624 BT_ASSERT(*struct_decl
);
1626 if (min_align_value
!= 0) {
1627 (*struct_decl
)->base
.alignment
= min_align_value
;
1630 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1632 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1633 ret
= visit_struct_decl_entry(ctx
, entry_node
, *struct_decl
);
1635 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
,
1636 "Cannot visit structure field class entry: "
1647 ret
= ctx_decl_scope_register_struct(ctx
->current_scope
, name
, *struct_decl
);
1649 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1651 "Cannot register structure field class in declaration scope: "
1652 "name=\"struct {}\", ret={}",
1662 ctf_field_class_destroy(&(*struct_decl
)->base
);
1663 *struct_decl
= NULL
;
1667 static int visit_variant_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1668 const char *tag
, struct bt_list_head
*decl_list
, int has_body
,
1669 struct ctf_field_class_variant
**variant_decl
)
1672 struct ctf_field_class_variant
*untagged_variant_decl
= NULL
;
1674 BT_ASSERT(variant_decl
);
1675 *variant_decl
= NULL
;
1677 /* For named variant (without body), lookup in declaration scope */
1680 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1681 "Bodyless variant field class: missing name.");
1686 untagged_variant_decl
= ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, -1, true);
1687 if (!untagged_variant_decl
) {
1688 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1689 ctx
->logger
, "Cannot find variant field class: name=\"variant {}\"", name
);
1694 struct ctf_node
*entry_node
;
1697 if (ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, 1, false)) {
1698 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1699 "Variant field class already declared in local scope: "
1700 "name=\"variant {}\"",
1707 untagged_variant_decl
= ctf_field_class_variant_create();
1708 BT_ASSERT(untagged_variant_decl
);
1709 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1711 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1712 ret
= visit_variant_decl_entry(ctx
, entry_node
, untagged_variant_decl
);
1714 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
,
1715 "Cannot visit variant field class entry: "
1726 ret
= ctx_decl_scope_register_variant(ctx
->current_scope
, name
, untagged_variant_decl
);
1728 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1730 "Cannot register variant field class in declaration scope: "
1731 "name=\"variant {}\", ret={}",
1739 * If tagged, create tagged variant and return; otherwise
1740 * return untagged variant.
1743 *variant_decl
= untagged_variant_decl
;
1744 untagged_variant_decl
= NULL
;
1747 * At this point, we have a fresh untagged variant; nobody
1748 * else owns it. Set its tag now.
1750 g_string_assign(untagged_variant_decl
->tag_ref
, tag
);
1751 *variant_decl
= untagged_variant_decl
;
1752 untagged_variant_decl
= NULL
;
1755 BT_ASSERT(!untagged_variant_decl
);
1756 BT_ASSERT(*variant_decl
);
1760 ctf_field_class_destroy(&untagged_variant_decl
->base
);
1761 untagged_variant_decl
= NULL
;
1762 ctf_field_class_destroy(&(*variant_decl
)->base
);
1763 *variant_decl
= NULL
;
1777 static int visit_enum_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*enumerator
,
1778 struct ctf_field_class_enum
*enum_decl
, struct uori
*last
)
1782 struct ctf_node
*iter
;
1783 struct uori start
= {
1797 const char *label
= enumerator
->u
.enumerator
.id
;
1798 struct bt_list_head
*values
= &enumerator
->u
.enumerator
.values
;
1800 bt_list_for_each_entry (iter
, values
, siblings
) {
1801 struct uori
*target
;
1803 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
1804 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
1805 "Wrong expression for enumeration field class label: "
1806 "node-type={}, label=\"{}\"",
1818 switch (iter
->u
.unary_expression
.type
) {
1819 case UNARY_SIGNED_CONSTANT
:
1820 target
->is_signed
= true;
1821 target
->value
.i
= iter
->u
.unary_expression
.u
.signed_constant
;
1823 case UNARY_UNSIGNED_CONSTANT
:
1824 target
->is_signed
= false;
1825 target
->value
.u
= iter
->u
.unary_expression
.u
.unsigned_constant
;
1828 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
1829 "Invalid enumeration field class entry: "
1830 "expecting constant signed or unsigned integer: "
1831 "node-type={}, label=\"{}\"",
1832 iter
->u
.unary_expression
.type
, label
);
1838 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1839 iter
, "Invalid enumeration field class entry: label=\"{}\"", label
);
1855 if (end
.is_signed
) {
1856 last
->value
.i
= end
.value
.i
+ 1;
1858 last
->value
.u
= end
.value
.u
+ 1;
1861 ctf_field_class_enum_map_range(enum_decl
, label
, start
.value
.u
, end
.value
.u
);
1868 static int visit_enum_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1869 struct ctf_node
*container_cls
, struct bt_list_head
*enumerator_list
,
1870 int has_body
, struct ctf_field_class_enum
**enum_decl
)
1874 struct ctf_field_class_int
*integer_decl
= NULL
;
1876 BT_ASSERT(enum_decl
);
1879 /* For named enum (without body), lookup in declaration scope */
1882 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1883 "Bodyless enumeration field class: missing name.");
1888 *enum_decl
= ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, -1, true);
1890 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1891 "Cannot find enumeration field class: "
1898 struct ctf_node
*iter
;
1899 struct uori last_value
= {
1908 if (ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, 1, false)) {
1909 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1911 "Enumeration field class already declared in local scope: "
1919 if (!container_cls
) {
1920 integer_decl
= ctf_field_class_as_int(
1921 ctx_decl_scope_lookup_alias(ctx
->current_scope
, "int", -1, true));
1922 if (!integer_decl
) {
1923 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1925 "Cannot find implicit `int` field class alias for enumeration field class.");
1930 ctf_field_class
*decl
;
1932 ret
= visit_field_class_declarator(ctx
, container_cls
, &qdummy_id
, NULL
, &decl
, NULL
);
1939 integer_decl
= ctf_field_class_as_int(decl
);
1942 BT_ASSERT(integer_decl
);
1944 if (integer_decl
->base
.base
.type
!= CTF_FIELD_CLASS_TYPE_INT
) {
1945 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1947 "Container field class for enumeration field class is not an integer field class: "
1949 integer_decl
->base
.base
.type
);
1954 *enum_decl
= ctf_field_class_enum_create();
1955 BT_ASSERT(*enum_decl
);
1956 (*enum_decl
)->base
.base
.base
.alignment
= integer_decl
->base
.base
.alignment
;
1957 ctf_field_class_int_copy_content(&(*enum_decl
)->base
, integer_decl
);
1958 last_value
.is_signed
= (*enum_decl
)->base
.is_signed
;
1960 bt_list_for_each_entry (iter
, enumerator_list
, siblings
) {
1961 ret
= visit_enum_decl_entry(ctx
, iter
, *enum_decl
, &last_value
);
1963 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
1964 "Cannot visit enumeration field class entry: "
1972 ret
= ctx_decl_scope_register_enum(ctx
->current_scope
, name
, *enum_decl
);
1974 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1976 "Cannot register enumeration field class in declaration scope: "
1987 ctf_field_class_destroy(&(*enum_decl
)->base
.base
.base
);
1991 ctf_field_class_destroy(&integer_decl
->base
.base
);
1992 integer_decl
= NULL
;
1996 static int visit_field_class_specifier(struct ctf_visitor_generate_ir
*ctx
,
1997 struct ctf_node
*cls_specifier_list
,
1998 struct ctf_field_class
**decl
)
2001 GString
*str
= NULL
;
2004 str
= g_string_new("");
2005 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
2007 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2008 "Cannot get field class specifier list's name: ret={}", ret
);
2012 *decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, str
->str
, -1, true);
2014 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2015 "Cannot find field class alias: name=\"{}\"", str
->str
);
2023 ctf_field_class_destroy(*decl
);
2028 g_string_free(str
, TRUE
);
2034 static int visit_integer_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2035 struct ctf_field_class_int
**integer_decl
)
2040 struct ctf_node
*expression
;
2041 uint64_t alignment
= 0, size
= 0;
2042 struct ctf_clock_class
*mapped_clock_class
= NULL
;
2043 enum ctf_encoding encoding
= CTF_ENCODING_NONE
;
2044 bt_field_class_integer_preferred_display_base base
=
2045 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2046 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2048 *integer_decl
= NULL
;
2050 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2051 struct ctf_node
*left
, *right
;
2053 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2055 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2057 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2058 _BT_CPPLOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type={}",
2059 left
->u
.unary_expression
.type
);
2064 if (strcmp(left
->u
.unary_expression
.u
.string
, "signed") == 0) {
2065 if (_IS_SET(&set
, _INTEGER_SIGNED_SET
)) {
2066 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "signed", "integer field class");
2071 signedness
= get_boolean(ctx
, right
);
2072 if (signedness
< 0) {
2073 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2075 "Invalid boolean value for integer field class's `signed` attribute: "
2082 _SET(&set
, _INTEGER_SIGNED_SET
);
2083 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2084 if (_IS_SET(&set
, _INTEGER_BYTE_ORDER_SET
)) {
2085 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order", "integer field class");
2090 byte_order
= get_real_byte_order(ctx
, right
);
2091 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2092 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2094 "Invalid `byte_order` attribute in integer field class: "
2101 _SET(&set
, _INTEGER_BYTE_ORDER_SET
);
2102 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "size") == 0) {
2103 if (_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2104 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "size", "integer field class");
2109 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2110 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2111 "Invalid `size` attribute in integer field class: "
2112 "expecting unsigned constant integer: "
2114 right
->u
.unary_expression
.type
);
2119 size
= right
->u
.unary_expression
.u
.unsigned_constant
;
2121 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2122 "Invalid `size` attribute in integer field class: "
2123 "expecting positive constant integer: "
2128 } else if (size
> 64) {
2129 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2131 "Invalid `size` attribute in integer field class: "
2132 "integer fields over 64 bits are not supported as of this version: "
2139 _SET(&set
, _INTEGER_SIZE_SET
);
2140 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2141 if (_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2142 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "align", "integer field class");
2147 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2148 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2149 "Invalid `align` attribute in integer field class: "
2150 "expecting unsigned constant integer: "
2152 right
->u
.unary_expression
.type
);
2157 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2158 if (!is_align_valid(alignment
)) {
2159 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2160 "Invalid `align` attribute in integer field class: "
2161 "expecting power of two: "
2168 _SET(&set
, _INTEGER_ALIGN_SET
);
2169 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "base") == 0) {
2170 if (_IS_SET(&set
, _INTEGER_BASE_SET
)) {
2171 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "base", "integer field class");
2176 switch (right
->u
.unary_expression
.type
) {
2177 case UNARY_UNSIGNED_CONSTANT
:
2179 uint64_t constant
= right
->u
.unary_expression
.u
.unsigned_constant
;
2183 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2186 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2189 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2192 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2195 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2197 "Invalid `base` attribute in integer field class: "
2199 right
->u
.unary_expression
.u
.unsigned_constant
);
2208 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2210 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2212 "Unexpected unary expression for integer field class's `base` attribute.");
2217 if (strcmp(s_right
, "decimal") == 0 || strcmp(s_right
, "dec") == 0 ||
2218 strcmp(s_right
, "d") == 0 || strcmp(s_right
, "i") == 0 ||
2219 strcmp(s_right
, "u") == 0) {
2220 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2221 } else if (strcmp(s_right
, "hexadecimal") == 0 || strcmp(s_right
, "hex") == 0 ||
2222 strcmp(s_right
, "x") == 0 || strcmp(s_right
, "X") == 0 ||
2223 strcmp(s_right
, "p") == 0) {
2224 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2225 } else if (strcmp(s_right
, "octal") == 0 || strcmp(s_right
, "oct") == 0 ||
2226 strcmp(s_right
, "o") == 0) {
2227 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2228 } else if (strcmp(s_right
, "binary") == 0 || strcmp(s_right
, "b") == 0) {
2229 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2231 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2233 "Unexpected unary expression for integer field class's `base` attribute: "
2245 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2246 right
, "Invalid `base` attribute in integer field class: "
2247 "expecting unsigned constant integer or unary string.");
2252 _SET(&set
, _INTEGER_BASE_SET
);
2253 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2256 if (_IS_SET(&set
, _INTEGER_ENCODING_SET
)) {
2257 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "integer field class");
2262 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2263 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2264 right
, "Invalid `encoding` attribute in integer field class: "
2265 "expecting unary string.");
2270 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2272 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2274 "Unexpected unary expression for integer field class's `encoding` attribute.");
2279 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2280 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2281 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2282 encoding
= CTF_ENCODING_UTF8
;
2283 } else if (strcmp(s_right
, "none") == 0) {
2284 encoding
= CTF_ENCODING_NONE
;
2286 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2288 "Invalid `encoding` attribute in integer field class: "
2289 "unknown encoding: encoding=\"{}\"",
2297 _SET(&set
, _INTEGER_ENCODING_SET
);
2298 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "map") == 0) {
2299 const char *clock_name
;
2301 if (_IS_SET(&set
, _INTEGER_MAP_SET
)) {
2302 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "map", "integer field class");
2307 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2308 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2309 "Invalid `map` attribute in integer field class: "
2310 "expecting unary string.");
2315 clock_name
= get_map_clock_name_value(&expression
->u
.ctf_expression
.right
);
2318 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2321 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2323 "Unexpected unary expression for integer field class's `map` attribute.");
2328 _BT_CPPLOGE_NODE(right
,
2329 "Invalid `map` attribute in integer field class: "
2330 "cannot find clock class at this point: name=\"{}\"",
2332 _SET(&set
, _INTEGER_MAP_SET
);
2337 mapped_clock_class
=
2338 ctf_trace_class_borrow_clock_class_by_name(ctx
->ctf_tc
, clock_name
);
2339 if (!mapped_clock_class
) {
2340 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2341 "Invalid `map` attribute in integer field class: "
2342 "cannot find clock class at this point: name=\"{}\"",
2348 _SET(&set
, _INTEGER_MAP_SET
);
2350 _BT_CPPLOGW_NODE(left
,
2351 "Unknown attribute in integer field class: "
2353 left
->u
.unary_expression
.u
.string
);
2357 if (!_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2358 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
2359 "Missing `size` attribute in integer field class.");
2364 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2365 if (size
% CHAR_BIT
) {
2366 /* Bit-packed alignment */
2369 /* Byte-packed alignment */
2370 alignment
= CHAR_BIT
;
2374 *integer_decl
= ctf_field_class_int_create();
2375 BT_ASSERT(*integer_decl
);
2376 (*integer_decl
)->base
.base
.alignment
= alignment
;
2377 (*integer_decl
)->base
.byte_order
= byte_order
;
2378 (*integer_decl
)->base
.size
= size
;
2379 (*integer_decl
)->is_signed
= (signedness
> 0);
2380 (*integer_decl
)->disp_base
= base
;
2381 (*integer_decl
)->encoding
= encoding
;
2382 (*integer_decl
)->mapped_clock_class
= mapped_clock_class
;
2386 ctf_field_class_destroy(&(*integer_decl
)->base
.base
);
2387 *integer_decl
= NULL
;
2391 static int visit_floating_point_number_decl(struct ctf_visitor_generate_ir
*ctx
,
2392 struct bt_list_head
*expressions
,
2393 struct ctf_field_class_float
**float_decl
)
2397 struct ctf_node
*expression
;
2398 uint64_t alignment
= 1, exp_dig
= 0, mant_dig
= 0;
2399 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2403 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2404 struct ctf_node
*left
, *right
;
2406 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2408 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2410 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2411 _BT_CPPLOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type={}",
2412 left
->u
.unary_expression
.type
);
2417 if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2418 if (_IS_SET(&set
, _FLOAT_BYTE_ORDER_SET
)) {
2419 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order",
2420 "floating point number field class");
2425 byte_order
= get_real_byte_order(ctx
, right
);
2426 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2427 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2429 "Invalid `byte_order` attribute in floating point number field class: "
2436 _SET(&set
, _FLOAT_BYTE_ORDER_SET
);
2437 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "exp_dig") == 0) {
2438 if (_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2439 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "exp_dig",
2440 "floating point number field class");
2445 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2446 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2448 "Invalid `exp_dig` attribute in floating point number field class: "
2449 "expecting unsigned constant integer: "
2451 right
->u
.unary_expression
.type
);
2456 exp_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2457 _SET(&set
, _FLOAT_EXP_DIG_SET
);
2458 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "mant_dig") == 0) {
2459 if (_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2460 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "mant_dig",
2461 "floating point number field class");
2466 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2467 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2469 "Invalid `mant_dig` attribute in floating point number field class: "
2470 "expecting unsigned constant integer: "
2472 right
->u
.unary_expression
.type
);
2477 mant_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2478 _SET(&set
, _FLOAT_MANT_DIG_SET
);
2479 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2480 if (_IS_SET(&set
, _FLOAT_ALIGN_SET
)) {
2481 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "align",
2482 "floating point number field class");
2487 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2488 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2490 "Invalid `align` attribute in floating point number field class: "
2491 "expecting unsigned constant integer: "
2493 right
->u
.unary_expression
.type
);
2498 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2500 if (!is_align_valid(alignment
)) {
2501 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2503 "Invalid `align` attribute in floating point number field class: "
2504 "expecting power of two: "
2511 _SET(&set
, _FLOAT_ALIGN_SET
);
2513 _BT_CPPLOGW_NODE(left
,
2514 "Unknown attribute in floating point number field class: "
2516 left
->u
.unary_expression
.u
.string
);
2520 if (!_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2521 BT_CPPLOGE_APPEND_CAUSE_SPEC(
2522 ctx
->logger
, "Missing `mant_dig` attribute in floating point number field class.");
2527 if (!_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2528 BT_CPPLOGE_APPEND_CAUSE_SPEC(
2529 ctx
->logger
, "Missing `exp_dig` attribute in floating point number field class.");
2534 if (mant_dig
!= 24 && mant_dig
!= 53) {
2535 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "`mant_dig` attribute: expecting 24 or 53.");
2540 if (mant_dig
== 24 && exp_dig
!= 8) {
2541 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
2542 "`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2547 if (mant_dig
== 53 && exp_dig
!= 11) {
2548 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
2549 "`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2554 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2555 if ((mant_dig
+ exp_dig
) % CHAR_BIT
) {
2556 /* Bit-packed alignment */
2559 /* Byte-packed alignment */
2560 alignment
= CHAR_BIT
;
2564 *float_decl
= ctf_field_class_float_create();
2565 BT_ASSERT(*float_decl
);
2566 (*float_decl
)->base
.base
.alignment
= alignment
;
2567 (*float_decl
)->base
.byte_order
= byte_order
;
2568 (*float_decl
)->base
.size
= mant_dig
+ exp_dig
;
2572 ctf_field_class_destroy(&(*float_decl
)->base
.base
);
2577 static int visit_string_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2578 struct ctf_field_class_string
**string_decl
)
2582 struct ctf_node
*expression
;
2583 enum ctf_encoding encoding
= CTF_ENCODING_UTF8
;
2585 *string_decl
= NULL
;
2587 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2588 struct ctf_node
*left
, *right
;
2590 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2592 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2594 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2595 _BT_CPPLOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type={}",
2596 left
->u
.unary_expression
.type
);
2601 if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2604 if (_IS_SET(&set
, _STRING_ENCODING_SET
)) {
2605 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "string field class");
2610 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2611 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2612 "Invalid `encoding` attribute in string field class: "
2613 "expecting unary string.");
2618 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2620 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2622 "Unexpected unary expression for string field class's `encoding` attribute.");
2627 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2628 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2629 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2630 encoding
= CTF_ENCODING_UTF8
;
2631 } else if (strcmp(s_right
, "none") == 0) {
2632 encoding
= CTF_ENCODING_NONE
;
2634 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2635 "Invalid `encoding` attribute in string field class: "
2636 "unknown encoding: encoding=\"{}\"",
2644 _SET(&set
, _STRING_ENCODING_SET
);
2646 _BT_CPPLOGW_NODE(left
,
2647 "Unknown attribute in string field class: "
2649 left
->u
.unary_expression
.u
.string
);
2653 *string_decl
= ctf_field_class_string_create();
2654 BT_ASSERT(*string_decl
);
2655 (*string_decl
)->encoding
= encoding
;
2659 ctf_field_class_destroy(&(*string_decl
)->base
);
2660 *string_decl
= NULL
;
2664 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
2665 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
)
2668 struct ctf_node
*first
, *node
;
2672 if (ts_list
->type
!= NODE_TYPE_SPECIFIER_LIST
) {
2673 _BT_CPPLOGE_APPEND_CAUSE_NODE(ts_list
, "Unexpected node type: node-type={}", ts_list
->type
);
2678 first
= _BT_LIST_FIRST_ENTRY(&ts_list
->u
.field_class_specifier_list
.head
, struct ctf_node
,
2680 if (first
->type
!= NODE_TYPE_SPECIFIER
) {
2681 _BT_CPPLOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type={}", first
->type
);
2686 node
= first
->u
.field_class_specifier
.node
;
2688 switch (first
->u
.field_class_specifier
.type
) {
2689 case TYPESPEC_INTEGER
:
2691 ctf_field_class_int
*int_decl
;
2693 ret
= visit_integer_decl(ctx
, &node
->u
.integer
.expressions
, &int_decl
);
2695 BT_ASSERT(!int_decl
);
2699 *decl
= &int_decl
->base
.base
;
2702 case TYPESPEC_FLOATING_POINT
:
2704 ctf_field_class_float
*float_decl
;
2707 visit_floating_point_number_decl(ctx
, &node
->u
.floating_point
.expressions
, &float_decl
);
2709 BT_ASSERT(!float_decl
);
2713 *decl
= &float_decl
->base
.base
;
2716 case TYPESPEC_STRING
:
2718 ctf_field_class_string
*string_decl
;
2720 ret
= visit_string_decl(ctx
, &node
->u
.string
.expressions
, &string_decl
);
2722 BT_ASSERT(!string_decl
);
2726 *decl
= &string_decl
->base
;
2729 case TYPESPEC_STRUCT
:
2731 ctf_field_class_struct
*struct_decl
;
2733 ret
= visit_struct_decl(ctx
, node
->u
._struct
.name
, &node
->u
._struct
.declaration_list
,
2734 node
->u
._struct
.has_body
, &node
->u
._struct
.min_align
, &struct_decl
);
2736 BT_ASSERT(!struct_decl
);
2740 *decl
= &struct_decl
->base
;
2743 case TYPESPEC_VARIANT
:
2745 ctf_field_class_variant
*variant_decl
;
2747 ret
= visit_variant_decl(ctx
, node
->u
.variant
.name
, node
->u
.variant
.choice
,
2748 &node
->u
.variant
.declaration_list
, node
->u
.variant
.has_body
,
2751 BT_ASSERT(!variant_decl
);
2755 *decl
= &variant_decl
->base
;
2760 ctf_field_class_enum
*enum_decl
;
2762 ret
= visit_enum_decl(ctx
, node
->u
._enum
.enum_id
, node
->u
._enum
.container_field_class
,
2763 &node
->u
._enum
.enumerator_list
, node
->u
._enum
.has_body
, &enum_decl
);
2765 BT_ASSERT(!enum_decl
);
2769 *decl
= &enum_decl
->base
.base
.base
;
2774 case TYPESPEC_SHORT
:
2777 case TYPESPEC_FLOAT
:
2778 case TYPESPEC_DOUBLE
:
2779 case TYPESPEC_SIGNED
:
2780 case TYPESPEC_UNSIGNED
:
2782 case TYPESPEC_COMPLEX
:
2783 case TYPESPEC_IMAGINARY
:
2784 case TYPESPEC_CONST
:
2785 case TYPESPEC_ID_TYPE
:
2786 ret
= visit_field_class_specifier(ctx
, ts_list
, decl
);
2788 _BT_CPPLOGE_APPEND_CAUSE_NODE(first
, "Cannot visit field class specifier: ret={}", ret
);
2794 _BT_CPPLOGE_APPEND_CAUSE_NODE(first
, "Unexpected field class specifier type: node-type={}",
2795 first
->u
.field_class_specifier
.type
);
2804 ctf_field_class_destroy(*decl
);
2809 static int visit_event_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
2810 struct ctf_event_class
*event_class
, uint64_t *stream_id
,
2816 switch (node
->type
) {
2818 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
2819 &node
->u
.field_class_def
.field_class_declarators
);
2821 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in event class.");
2825 case NODE_TYPEALIAS
:
2826 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
2827 node
->u
.field_class_alias
.alias
);
2829 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
2830 "Cannot add field class alias found in event class.");
2834 case NODE_CTF_EXPRESSION
:
2836 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
2838 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
2843 if (strcmp(left
, "name") == 0) {
2844 /* This is already known at this stage */
2845 if (_IS_SET(set
, _EVENT_NAME_SET
)) {
2846 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "name", "event class");
2851 _SET(set
, _EVENT_NAME_SET
);
2852 } else if (strcmp(left
, "id") == 0) {
2855 if (_IS_SET(set
, _EVENT_ID_SET
)) {
2856 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "event class");
2861 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
2862 /* Only read "id" if get_unary_unsigned() succeeded. */
2863 if (ret
|| (!ret
&& id
< 0)) {
2864 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2865 node
, "Unexpected unary expression for event class's `id` attribute.");
2870 event_class
->id
= id
;
2871 _SET(set
, _EVENT_ID_SET
);
2872 } else if (strcmp(left
, "stream_id") == 0) {
2873 if (_IS_SET(set
, _EVENT_STREAM_ID_SET
)) {
2874 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "stream_id", "event class");
2879 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, stream_id
);
2882 * Only read "stream_id" if get_unary_unsigned()
2886 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2887 node
, "Unexpected unary expression for event class's `stream_id` attribute.");
2892 _SET(set
, _EVENT_STREAM_ID_SET
);
2893 } else if (strcmp(left
, "context") == 0) {
2894 if (_IS_SET(set
, _EVENT_CONTEXT_SET
)) {
2895 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate `context` entry in event class.");
2900 ret
= visit_field_class_specifier_list(
2901 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2902 &event_class
->spec_context_fc
);
2904 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
2905 "Cannot create event class's context field class.");
2909 BT_ASSERT(event_class
->spec_context_fc
);
2910 _SET(set
, _EVENT_CONTEXT_SET
);
2911 } else if (strcmp(left
, "fields") == 0) {
2912 if (_IS_SET(set
, _EVENT_FIELDS_SET
)) {
2913 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate `fields` entry in event class.");
2918 ret
= visit_field_class_specifier_list(
2919 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2920 &event_class
->payload_fc
);
2922 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
2923 "Cannot create event class's payload field class.");
2927 BT_ASSERT(event_class
->payload_fc
);
2928 _SET(set
, _EVENT_FIELDS_SET
);
2929 } else if (strcmp(left
, "loglevel") == 0) {
2930 uint64_t loglevel_value
;
2931 bool is_log_level_known
= true;
2932 bt_event_class_log_level log_level
;
2934 if (_IS_SET(set
, _EVENT_LOG_LEVEL_SET
)) {
2935 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "loglevel", "event class");
2940 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &loglevel_value
);
2942 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2943 node
, "Unexpected unary expression for event class's `loglevel` attribute.");
2948 switch (loglevel_value
) {
2950 log_level
= BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
;
2953 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ALERT
;
2956 log_level
= BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
;
2959 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ERROR
;
2962 log_level
= BT_EVENT_CLASS_LOG_LEVEL_WARNING
;
2965 log_level
= BT_EVENT_CLASS_LOG_LEVEL_NOTICE
;
2968 log_level
= BT_EVENT_CLASS_LOG_LEVEL_INFO
;
2971 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
;
2974 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
;
2977 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
;
2980 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
;
2983 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
;
2986 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
;
2989 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
;
2992 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG
;
2995 is_log_level_known
= false;
2998 "Not setting event class's log level because its value is unknown: "
3003 if (is_log_level_known
) {
3004 ctf_event_class_set_log_level(event_class
, log_level
);
3007 _SET(set
, _EVENT_LOG_LEVEL_SET
);
3008 } else if (strcmp(left
, "model.emf.uri") == 0) {
3011 if (_IS_SET(set
, _EVENT_MODEL_EMF_URI_SET
)) {
3012 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "model.emf.uri", "event class");
3017 right
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.right
);
3019 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3021 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3026 if (strlen(right
) == 0) {
3027 _BT_CPPLOGW_NODE(node
, "Not setting event class's EMF URI because it's empty.");
3029 g_string_assign(event_class
->emf_uri
, right
);
3033 _SET(set
, _EVENT_MODEL_EMF_URI_SET
);
3035 _BT_CPPLOGW_NODE(node
,
3036 "Unknown attribute in event class: "
3059 static char *get_event_decl_name(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3063 struct ctf_node
*iter
;
3064 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3066 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3067 if (iter
->type
!= NODE_CTF_EXPRESSION
) {
3071 left
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.left
);
3073 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot concatenate unary strings.");
3077 if (strcmp(left
, "name") == 0) {
3078 name
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.right
);
3080 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3081 iter
, "Unexpected unary expression for event class's `name` attribute.");
3101 static int visit_event_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3105 struct ctf_node
*iter
;
3106 uint64_t stream_id
= 0;
3107 char *event_name
= NULL
;
3108 struct ctf_event_class
*event_class
= NULL
;
3109 struct ctf_stream_class
*stream_class
= NULL
;
3110 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3111 bool pop_scope
= false;
3113 if (node
->visited
) {
3117 node
->visited
= TRUE
;
3118 event_name
= get_event_decl_name(ctx
, node
);
3120 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `name` attribute in event class.");
3125 event_class
= ctf_event_class_create();
3126 BT_ASSERT(event_class
);
3127 g_string_assign(event_class
->name
, event_name
);
3128 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3131 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3132 ret
= visit_event_decl_entry(ctx
, iter
, event_class
, &stream_id
, &set
);
3134 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
3135 "Cannot visit event class's entry: "
3142 if (!_IS_SET(&set
, _EVENT_STREAM_ID_SET
)) {
3144 * Allow missing stream_id if there is only a single
3147 switch (ctx
->ctf_tc
->stream_classes
->len
) {
3149 /* Create implicit stream class if there's none */
3151 stream_class
= ctf_stream_class_create();
3152 BT_ASSERT(stream_class
);
3153 stream_class
->id
= stream_id
;
3154 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3157 /* Single stream class: get its ID */
3158 stream_class
= (ctf_stream_class
*) ctx
->ctf_tc
->stream_classes
->pdata
[0];
3159 stream_id
= stream_class
->id
;
3162 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `stream_id` attribute in event class.");
3168 /* We have the stream ID now; get the stream class if found */
3169 if (!stream_class
) {
3170 stream_class
= ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_id
);
3171 if (!stream_class
) {
3172 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3173 "Cannot find stream class at this point: "
3181 BT_ASSERT(stream_class
);
3183 if (!_IS_SET(&set
, _EVENT_ID_SET
)) {
3184 /* Allow only one event without ID per stream */
3185 if (stream_class
->event_classes
->len
!= 0) {
3186 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `id` attribute in event class.");
3192 event_class
->id
= 0;
3195 if (ctf_stream_class_borrow_event_class_by_id(stream_class
, event_class
->id
)) {
3196 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3197 "Duplicate event class (same ID) in the same stream class: "
3204 ctf_stream_class_append_event_class(stream_class
, event_class
);
3209 ctf_event_class_destroy(event_class
);
3226 static int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3227 struct ctf_field_class
*fc
)
3229 struct ctf_clock_class
*clock_class_to_map_to
= NULL
;
3230 uint64_t clock_class_count
;
3236 if (fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&& fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3240 ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
3242 if (int_fc
->mapped_clock_class
) {
3243 /* Already mapped */
3247 clock_class_count
= ctx
->ctf_tc
->clock_classes
->len
;
3249 switch (clock_class_count
) {
3252 * No clock class exists in the trace at this point. Create an
3253 * implicit one at 1 GHz, named `default`, and use this clock
3256 clock_class_to_map_to
= ctf_clock_class_create();
3257 BT_ASSERT(clock_class_to_map_to
);
3258 clock_class_to_map_to
->frequency
= UINT64_C(1000000000);
3259 g_string_assign(clock_class_to_map_to
->name
, "default");
3260 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock_class_to_map_to
);
3264 * Only one clock class exists in the trace at this point: use
3267 clock_class_to_map_to
= (ctf_clock_class
*) ctx
->ctf_tc
->clock_classes
->pdata
[0];
3271 * Timestamp field not mapped to a clock class and there's more
3272 * than one clock class in the trace: this is an error.
3274 BT_CPPLOGE_APPEND_CAUSE_SPEC(
3275 ctx
->logger
, "Timestamp field found with no mapped clock class, "
3276 "but there's more than one clock class in the trace at this point.");
3280 BT_ASSERT(clock_class_to_map_to
);
3281 int_fc
->mapped_clock_class
= clock_class_to_map_to
;
3286 static int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3287 struct ctf_field_class
*root_fc
,
3288 const char *field_name
)
3292 struct ctf_field_class_struct
*struct_fc
= (ctf_field_class_struct
*) root_fc
;
3293 struct ctf_field_class_variant
*var_fc
= (ctf_field_class_variant
*) root_fc
;
3299 if (root_fc
->type
!= CTF_FIELD_CLASS_TYPE_STRUCT
&&
3300 root_fc
->type
!= CTF_FIELD_CLASS_TYPE_VARIANT
) {
3304 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3305 count
= struct_fc
->members
->len
;
3307 count
= var_fc
->options
->len
;
3310 for (i
= 0; i
< count
; i
++) {
3311 struct ctf_named_field_class
*named_fc
= NULL
;
3313 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3314 named_fc
= ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
3315 } else if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
3316 named_fc
= ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
3321 if (strcmp(named_fc
->name
->str
, field_name
) == 0) {
3322 ret
= auto_map_field_to_trace_clock_class(ctx
, named_fc
->fc
);
3324 BT_CPPLOGE_APPEND_CAUSE_SPEC(
3326 "Cannot automatically map field to trace's clock class: "
3327 "field-name=\"{}\"",
3333 ret
= auto_map_fields_to_trace_clock_class(ctx
, named_fc
->fc
, field_name
);
3335 BT_CPPLOGE_APPEND_CAUSE_SPEC(
3337 "Cannot automatically map structure or variant field class's fields to trace's clock class: "
3338 "field-name=\"{}\", root-field-name=\"{}\"",
3339 field_name
, named_fc
->name
->str
);
3348 static int visit_stream_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3349 struct ctf_stream_class
*stream_class
, int *set
)
3354 switch (node
->type
) {
3356 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3357 &node
->u
.field_class_def
.field_class_declarators
);
3359 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in stream class.");
3363 case NODE_TYPEALIAS
:
3364 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3365 node
->u
.field_class_alias
.alias
);
3367 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3368 "Cannot add field class alias found in stream class.");
3372 case NODE_CTF_EXPRESSION
:
3374 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3376 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3381 if (strcmp(left
, "id") == 0) {
3384 if (_IS_SET(set
, _STREAM_ID_SET
)) {
3385 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "stream declaration");
3390 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
3392 /* Only read "id" if get_unary_unsigned() succeeded. */
3393 if (ret
|| (!ret
&& id
< 0)) {
3394 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3395 node
, "Unexpected unary expression for stream class's `id` attribute.");
3400 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, id
)) {
3401 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate stream class (same ID): id={}", id
);
3406 stream_class
->id
= id
;
3407 _SET(set
, _STREAM_ID_SET
);
3408 } else if (strcmp(left
, "event.header") == 0) {
3409 if (_IS_SET(set
, _STREAM_EVENT_HEADER_SET
)) {
3410 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3411 "Duplicate `event.header` entry in stream class.");
3416 ret
= visit_field_class_specifier_list(
3417 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3418 &stream_class
->event_header_fc
);
3420 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3421 node
, "Cannot create stream class's event header field class.");
3425 BT_ASSERT(stream_class
->event_header_fc
);
3426 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->event_header_fc
,
3429 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3431 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3435 _SET(set
, _STREAM_EVENT_HEADER_SET
);
3436 } else if (strcmp(left
, "event.context") == 0) {
3437 if (_IS_SET(set
, _STREAM_EVENT_CONTEXT_SET
)) {
3438 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3439 "Duplicate `event.context` entry in stream class.");
3444 ret
= visit_field_class_specifier_list(
3445 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3446 &stream_class
->event_common_context_fc
);
3448 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3449 node
, "Cannot create stream class's event context field class.");
3453 BT_ASSERT(stream_class
->event_common_context_fc
);
3454 _SET(set
, _STREAM_EVENT_CONTEXT_SET
);
3455 } else if (strcmp(left
, "packet.context") == 0) {
3456 if (_IS_SET(set
, _STREAM_PACKET_CONTEXT_SET
)) {
3457 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3458 "Duplicate `packet.context` entry in stream class.");
3463 ret
= visit_field_class_specifier_list(
3464 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3465 &stream_class
->packet_context_fc
);
3467 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3468 node
, "Cannot create stream class's packet context field class.");
3472 BT_ASSERT(stream_class
->packet_context_fc
);
3473 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3476 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3478 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3482 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3485 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3487 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3491 _SET(set
, _STREAM_PACKET_CONTEXT_SET
);
3493 _BT_CPPLOGW_NODE(node
,
3494 "Unknown attribute in stream class: "
3516 static int visit_stream_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3520 struct ctf_node
*iter
;
3521 struct ctf_stream_class
*stream_class
= NULL
;
3522 struct bt_list_head
*decl_list
= &node
->u
.stream
.declaration_list
;
3524 if (node
->visited
) {
3528 node
->visited
= TRUE
;
3529 stream_class
= ctf_stream_class_create();
3530 BT_ASSERT(stream_class
);
3531 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3533 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3534 ret
= visit_stream_decl_entry(ctx
, iter
, stream_class
, &set
);
3536 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
3537 "Cannot visit stream class's entry: "
3547 if (_IS_SET(&set
, _STREAM_ID_SET
)) {
3548 /* Check that packet header has `stream_id` field */
3549 struct ctf_named_field_class
*named_fc
= NULL
;
3551 if (!ctx
->ctf_tc
->packet_header_fc
) {
3552 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Stream class has a `id` attribute, "
3553 "but trace has no packet header field class.");
3558 named_fc
= ctf_field_class_struct_borrow_member_by_name(
3559 ctf_field_class_as_struct(ctx
->ctf_tc
->packet_header_fc
), "stream_id");
3561 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3562 node
, "Stream class has a `id` attribute, "
3563 "but trace's packet header field class has no `stream_id` field.");
3568 if (named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3569 named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3570 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3572 "Stream class has a `id` attribute, "
3573 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3578 /* Allow only _one_ ID-less stream */
3579 if (ctx
->ctf_tc
->stream_classes
->len
!= 0) {
3580 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3582 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3587 /* Automatic ID: 0 */
3588 stream_class
->id
= 0;
3592 * Make sure that this stream class's ID is currently unique in
3595 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_class
->id
)) {
3596 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate stream class (same ID): id={}",
3602 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3603 stream_class
= NULL
;
3607 ctf_stream_class_destroy(stream_class
);
3608 stream_class
= NULL
;
3614 static int visit_trace_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3621 switch (node
->type
) {
3623 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3624 &node
->u
.field_class_def
.field_class_declarators
);
3626 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3627 "Cannot add field class found in trace (`trace` block).");
3631 case NODE_TYPEALIAS
:
3632 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3633 node
->u
.field_class_alias
.alias
);
3635 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3636 node
, "Cannot add field class alias found in trace (`trace` block).");
3640 case NODE_CTF_EXPRESSION
:
3642 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3644 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3649 if (strcmp(left
, "major") == 0) {
3650 if (_IS_SET(set
, _TRACE_MAJOR_SET
)) {
3651 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "major", "trace");
3656 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3658 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3659 node
, "Unexpected unary expression for trace's `major` attribute.");
3665 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3666 "Invalid trace's `minor` attribute: expecting 1.");
3671 ctx
->ctf_tc
->major
= val
;
3672 _SET(set
, _TRACE_MAJOR_SET
);
3673 } else if (strcmp(left
, "minor") == 0) {
3674 if (_IS_SET(set
, _TRACE_MINOR_SET
)) {
3675 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "minor", "trace");
3680 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3682 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3683 node
, "Unexpected unary expression for trace's `minor` attribute.");
3689 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3690 "Invalid trace's `minor` attribute: expecting 8.");
3695 ctx
->ctf_tc
->minor
= val
;
3696 _SET(set
, _TRACE_MINOR_SET
);
3697 } else if (strcmp(left
, "uuid") == 0) {
3698 if (_IS_SET(set
, _TRACE_UUID_SET
)) {
3699 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "uuid", "trace");
3704 ret
= get_unary_uuid(ctx
, &node
->u
.ctf_expression
.right
, ctx
->ctf_tc
->uuid
);
3706 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Invalid trace's `uuid` attribute.");
3710 ctx
->ctf_tc
->is_uuid_set
= true;
3711 _SET(set
, _TRACE_UUID_SET
);
3712 } else if (strcmp(left
, "byte_order") == 0) {
3713 /* Default byte order is already known at this stage */
3714 if (_IS_SET(set
, _TRACE_BYTE_ORDER_SET
)) {
3715 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
3720 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
!= CTF_BYTE_ORDER_UNKNOWN
);
3721 _SET(set
, _TRACE_BYTE_ORDER_SET
);
3722 } else if (strcmp(left
, "packet.header") == 0) {
3723 if (_IS_SET(set
, _TRACE_PACKET_HEADER_SET
)) {
3724 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate `packet.header` entry in trace.");
3729 ret
= visit_field_class_specifier_list(
3730 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3731 &ctx
->ctf_tc
->packet_header_fc
);
3733 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3734 "Cannot create trace's packet header field class.");
3738 BT_ASSERT(ctx
->ctf_tc
->packet_header_fc
);
3739 _SET(set
, _TRACE_PACKET_HEADER_SET
);
3741 _BT_CPPLOGW_NODE(node
,
3742 "Unknown attribute in stream class: "
3752 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Unknown expression in trace.");
3764 static int visit_trace_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3768 struct ctf_node
*iter
;
3769 struct bt_list_head
*decl_list
= &node
->u
.trace
.declaration_list
;
3771 if (node
->visited
) {
3775 node
->visited
= TRUE
;
3777 if (ctx
->is_trace_visited
) {
3778 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
3783 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3785 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3786 ret
= visit_trace_decl_entry(ctx
, iter
, &set
);
3788 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
3789 "Cannot visit trace's entry (`trace` block): "
3799 if (!_IS_SET(&set
, _TRACE_MAJOR_SET
)) {
3800 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `major` attribute in trace (`trace` block).");
3805 if (!_IS_SET(&set
, _TRACE_MINOR_SET
)) {
3806 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `minor` attribute in trace (`trace` block).");
3811 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3812 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3813 "Missing `byte_order` attribute in trace (`trace` block).");
3818 ctx
->is_trace_visited
= true;
3827 static int visit_env(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3831 struct ctf_node
*entry_node
;
3832 struct bt_list_head
*decl_list
= &node
->u
.env
.declaration_list
;
3834 if (node
->visited
) {
3838 node
->visited
= TRUE
;
3840 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
3841 struct bt_list_head
*right_head
= &entry_node
->u
.ctf_expression
.right
;
3843 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
3844 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
,
3845 "Wrong expression in environment entry: "
3852 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
3854 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot get environment entry's name.");
3859 if (is_unary_string(right_head
)) {
3860 char *right
= ctf_ast_concatenate_unary_strings(right_head
);
3863 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3865 "Unexpected unary expression for environment entry's value: "
3872 if (strcmp(left
, "tracer_name") == 0) {
3873 if (strncmp(right
, "lttng", 5) == 0) {
3874 BT_CPPLOGI_SPEC(ctx
->logger
,
3875 "Detected LTTng trace from `{}` environment value: "
3876 "tracer-name=\"{}\"",
3878 ctx
->is_lttng
= true;
3882 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
,
3885 } else if (is_unary_unsigned(right_head
) || is_unary_signed(right_head
)) {
3888 if (is_unary_unsigned(right_head
)) {
3889 ret
= get_unary_unsigned(ctx
, right_head
, (uint64_t *) &v
);
3891 ret
= get_unary_signed(right_head
, &v
);
3894 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3896 "Unexpected unary expression for environment entry's value: "
3903 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
,
3906 _BT_CPPLOGW_NODE(entry_node
,
3907 "Environment entry has unknown type: "
3924 static int set_trace_byte_order(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*trace_node
)
3929 struct ctf_node
*node
;
3930 struct bt_list_head
*decl_list
= &trace_node
->u
.trace
.declaration_list
;
3932 bt_list_for_each_entry (node
, decl_list
, siblings
) {
3933 if (node
->type
== NODE_CTF_EXPRESSION
) {
3934 struct ctf_node
*right_node
;
3936 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3938 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3943 if (strcmp(left
, "byte_order") == 0) {
3944 enum ctf_byte_order bo
;
3946 if (_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3947 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
3952 _SET(&set
, _TRACE_BYTE_ORDER_SET
);
3954 _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
3955 bo
= byte_order_from_unary_expr(ctx
, right_node
);
3956 if (bo
== CTF_BYTE_ORDER_UNKNOWN
) {
3957 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3958 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
3959 "expecting `le`, `be`, or `network`.");
3962 } else if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
3963 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3964 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
3965 "cannot be set to `native` here.");
3970 ctx
->ctf_tc
->default_byte_order
= bo
;
3978 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3979 _BT_CPPLOGE_APPEND_CAUSE_NODE(trace_node
,
3980 "Missing `byte_order` attribute in trace (`trace` block).");
3992 static int visit_clock_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
3993 struct ctf_clock_class
*clock
, int *set
, int64_t *offset_seconds
,
3994 uint64_t *offset_cycles
)
3999 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4000 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type={}",
4006 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
4008 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot concatenate unary strings.");
4013 if (strcmp(left
, "name") == 0) {
4016 if (_IS_SET(set
, _CLOCK_NAME_SET
)) {
4017 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "name", "clock class");
4022 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4024 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4025 entry_node
, "Unexpected unary expression for clock class's `name` attribute.");
4030 g_string_assign(clock
->name
, right
);
4032 _SET(set
, _CLOCK_NAME_SET
);
4033 } else if (strcmp(left
, "uuid") == 0) {
4036 if (_IS_SET(set
, _CLOCK_UUID_SET
)) {
4037 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "uuid", "clock class");
4042 ret
= get_unary_uuid(ctx
, &entry_node
->u
.ctf_expression
.right
, uuid
);
4044 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Invalid clock class's `uuid` attribute.");
4048 clock
->has_uuid
= true;
4049 bt_uuid_copy(clock
->uuid
, uuid
);
4050 _SET(set
, _CLOCK_UUID_SET
);
4051 } else if (strcmp(left
, "description") == 0) {
4054 if (_IS_SET(set
, _CLOCK_DESCRIPTION_SET
)) {
4055 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "description", "clock class");
4060 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4062 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4064 "Unexpected unary expression for clock class's `description` attribute.");
4069 g_string_assign(clock
->description
, right
);
4071 _SET(set
, _CLOCK_DESCRIPTION_SET
);
4072 } else if (strcmp(left
, "freq") == 0) {
4073 uint64_t freq
= UINT64_C(-1);
4075 if (_IS_SET(set
, _CLOCK_FREQ_SET
)) {
4076 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "freq", "clock class");
4081 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &freq
);
4083 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4084 entry_node
, "Unexpected unary expression for clock class's `freq` attribute.");
4089 if (freq
== UINT64_C(-1) || freq
== 0) {
4090 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Invalid clock class frequency: freq={}",
4096 clock
->frequency
= freq
;
4097 _SET(set
, _CLOCK_FREQ_SET
);
4098 } else if (strcmp(left
, "precision") == 0) {
4101 if (_IS_SET(set
, _CLOCK_PRECISION_SET
)) {
4102 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "precision", "clock class");
4107 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &precision
);
4109 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4110 entry_node
, "Unexpected unary expression for clock class's `precision` attribute.");
4115 clock
->precision
= precision
;
4116 _SET(set
, _CLOCK_PRECISION_SET
);
4117 } else if (strcmp(left
, "offset_s") == 0) {
4118 if (_IS_SET(set
, _CLOCK_OFFSET_S_SET
)) {
4119 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset_s", "clock class");
4124 ret
= get_unary_signed(&entry_node
->u
.ctf_expression
.right
, offset_seconds
);
4126 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4127 entry_node
, "Unexpected unary expression for clock class's `offset_s` attribute.");
4132 _SET(set
, _CLOCK_OFFSET_S_SET
);
4133 } else if (strcmp(left
, "offset") == 0) {
4134 if (_IS_SET(set
, _CLOCK_OFFSET_SET
)) {
4135 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset", "clock class");
4140 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, offset_cycles
);
4142 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4143 entry_node
, "Unexpected unary expression for clock class's `offset` attribute.");
4148 _SET(set
, _CLOCK_OFFSET_SET
);
4149 } else if (strcmp(left
, "absolute") == 0) {
4150 struct ctf_node
*right
;
4152 if (_IS_SET(set
, _CLOCK_ABSOLUTE_SET
)) {
4153 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "absolute", "clock class");
4159 _BT_LIST_FIRST_ENTRY(&entry_node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4160 ret
= get_boolean(ctx
, right
);
4162 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4163 entry_node
, "Unexpected unary expression for clock class's `absolute` attribute.");
4168 clock
->is_absolute
= ret
;
4169 _SET(set
, _CLOCK_ABSOLUTE_SET
);
4171 _BT_CPPLOGW_NODE(entry_node
, "Unknown attribute in clock class: attr-name=\"{}\"", left
);
4183 static inline uint64_t cycles_from_ns(uint64_t frequency
, uint64_t ns
)
4188 if (frequency
== UINT64_C(1000000000)) {
4191 cycles
= (uint64_t) (((double) ns
* (double) frequency
) / 1e9
);
4197 static void calibrate_clock_class_offsets(int64_t *offset_seconds
, uint64_t *offset_cycles
,
4200 if (*offset_cycles
>= freq
) {
4201 const uint64_t s_in_offset_cycles
= *offset_cycles
/ freq
;
4203 *offset_seconds
+= (int64_t) s_in_offset_cycles
;
4204 *offset_cycles
-= (s_in_offset_cycles
* freq
);
4208 static void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir
*ctx
,
4209 struct ctf_clock_class
*clock
)
4211 if (ctx
->decoder_config
.clkClsCfg
.forceOriginIsUnixEpoch
) {
4212 clock
->is_absolute
= true;
4218 static void apply_clock_class_offset(struct ctf_visitor_generate_ir
*ctx
,
4219 struct ctf_clock_class
*clock
)
4222 int64_t offset_s_to_apply
= ctx
->decoder_config
.clkClsCfg
.offsetSec
;
4223 uint64_t offset_ns_to_apply
;
4224 int64_t cur_offset_s
;
4225 uint64_t cur_offset_cycles
;
4227 if (ctx
->decoder_config
.clkClsCfg
.offsetSec
== 0 &&
4228 ctx
->decoder_config
.clkClsCfg
.offsetNanoSec
== 0) {
4232 /* Transfer nanoseconds to seconds as much as possible */
4233 if (ctx
->decoder_config
.clkClsCfg
.offsetNanoSec
< 0) {
4234 const int64_t abs_ns
= -ctx
->decoder_config
.clkClsCfg
.offsetNanoSec
;
4235 const int64_t abs_extra_s
= abs_ns
/ INT64_C(1000000000) + 1;
4236 const int64_t extra_s
= -abs_extra_s
;
4237 const int64_t offset_ns
=
4238 ctx
->decoder_config
.clkClsCfg
.offsetNanoSec
- (extra_s
* INT64_C(1000000000));
4240 BT_ASSERT(offset_ns
> 0);
4241 offset_ns_to_apply
= (uint64_t) offset_ns
;
4242 offset_s_to_apply
+= extra_s
;
4244 const int64_t extra_s
= ctx
->decoder_config
.clkClsCfg
.offsetNanoSec
/ INT64_C(1000000000);
4245 const int64_t offset_ns
=
4246 ctx
->decoder_config
.clkClsCfg
.offsetNanoSec
- (extra_s
* INT64_C(1000000000));
4248 BT_ASSERT(offset_ns
>= 0);
4249 offset_ns_to_apply
= (uint64_t) offset_ns
;
4250 offset_s_to_apply
+= extra_s
;
4253 freq
= clock
->frequency
;
4254 cur_offset_s
= clock
->offset_seconds
;
4255 cur_offset_cycles
= clock
->offset_cycles
;
4258 cur_offset_s
+= offset_s_to_apply
;
4259 cur_offset_cycles
+= cycles_from_ns(freq
, offset_ns_to_apply
);
4262 * Recalibrate offsets because the part in cycles can be greater
4263 * than the frequency at this point.
4265 calibrate_clock_class_offsets(&cur_offset_s
, &cur_offset_cycles
, freq
);
4267 /* Set final offsets */
4268 clock
->offset_seconds
= cur_offset_s
;
4269 clock
->offset_cycles
= cur_offset_cycles
;
4275 static int visit_clock_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*clock_node
)
4279 struct ctf_clock_class
*clock
;
4280 struct ctf_node
*entry_node
;
4281 struct bt_list_head
*decl_list
= &clock_node
->u
.clock
.declaration_list
;
4282 const char *clock_class_name
;
4283 int64_t offset_seconds
= 0;
4284 uint64_t offset_cycles
= 0;
4287 if (clock_node
->visited
) {
4291 clock_node
->visited
= TRUE
;
4293 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4294 clock
= ctf_clock_class_create();
4296 _BT_CPPLOGE_APPEND_CAUSE_NODE(clock_node
, "Cannot create default clock class.");
4301 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
4302 ret
= visit_clock_decl_entry(ctx
, entry_node
, clock
, &set
, &offset_seconds
, &offset_cycles
);
4304 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot visit clock class's entry: ret={}",
4310 if (!_IS_SET(&set
, _CLOCK_NAME_SET
)) {
4311 _BT_CPPLOGE_APPEND_CAUSE_NODE(clock_node
, "Missing `name` attribute in clock class.");
4316 clock_class_name
= clock
->name
->str
;
4317 BT_ASSERT(clock_class_name
);
4318 if (ctx
->is_lttng
&& strcmp(clock_class_name
, "monotonic") == 0) {
4320 * Old versions of LTTng forgot to set its clock class
4321 * as absolute, even if it is. This is important because
4322 * it's a condition to be able to sort messages
4323 * from different sources.
4325 clock
->is_absolute
= true;
4329 * Adjust offsets so that the part in cycles is less than the
4330 * frequency (move to the part in seconds).
4332 freq
= clock
->frequency
;
4333 calibrate_clock_class_offsets(&offset_seconds
, &offset_cycles
, freq
);
4334 BT_ASSERT(offset_cycles
< clock
->frequency
);
4335 clock
->offset_seconds
= offset_seconds
;
4336 clock
->offset_cycles
= offset_cycles
;
4337 apply_clock_class_offset(ctx
, clock
);
4338 apply_clock_class_is_absolute(ctx
, clock
);
4339 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock
);
4344 ctf_clock_class_destroy(clock
);
4350 static int visit_root_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*root_decl_node
)
4354 if (root_decl_node
->visited
) {
4358 root_decl_node
->visited
= TRUE
;
4360 switch (root_decl_node
->type
) {
4363 visit_field_class_def(ctx
, root_decl_node
->u
.field_class_def
.field_class_specifier_list
,
4364 &root_decl_node
->u
.field_class_def
.field_class_declarators
);
4366 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node
,
4367 "Cannot add field class found in root scope.");
4371 case NODE_TYPEALIAS
:
4372 ret
= visit_field_class_alias(ctx
, root_decl_node
->u
.field_class_alias
.target
,
4373 root_decl_node
->u
.field_class_alias
.alias
);
4375 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node
,
4376 "Cannot add field class alias found in root scope.");
4380 case NODE_TYPE_SPECIFIER_LIST
:
4382 struct ctf_field_class
*decl
= NULL
;
4385 * Just add the field class specifier to the root
4386 * declaration scope. Put local reference.
4388 ret
= visit_field_class_specifier_list(ctx
, root_decl_node
, &decl
);
4390 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node
,
4391 "Cannot visit root scope's field class: "
4398 ctf_field_class_destroy(decl
);
4403 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node
, "Unexpected node type: node-type={}",
4404 root_decl_node
->type
);
4413 ctf_visitor_generate_ir::UP
4414 ctf_visitor_generate_ir_create(const struct ctf_metadata_decoder_config
*decoder_config
)
4416 bt2c::Logger logger
{decoder_config
->logger
, "PLUGIN/CTF/META/IR-VISITOR"};
4418 /* Create visitor's context */
4419 ctf_visitor_generate_ir::UP ctx
= ctx_create(decoder_config
, logger
);
4422 BT_CPPLOGE_APPEND_CAUSE_SPEC(logger
, "Cannot create visitor's context.");
4435 static void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir
*visitor
)
4437 ctx_destroy(visitor
);
4440 void ctf_visitor_generate_ir_deleter::operator()(ctf_visitor_generate_ir
*visitor
)
4442 ctf_visitor_generate_ir_destroy(visitor
);
4445 bt_trace_class
*ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4449 if (ctx
->trace_class
) {
4450 bt_trace_class_get_ref(ctx
->trace_class
);
4453 return ctx
->trace_class
;
4456 struct ctf_trace_class
*
4457 ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4460 BT_ASSERT_DBG(ctx
->ctf_tc
);
4464 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
4468 BT_CPPLOGI_STR_SPEC(ctx
->logger
, "Visiting metadata's AST to generate CTF IR objects.");
4470 switch (node
->type
) {
4473 struct ctf_node
*iter
;
4474 bool got_trace_decl
= false;
4477 * The first thing we need is the native byte order of
4478 * the trace block, because early class aliases can have
4479 * a `byte_order` attribute set to `native`. If we don't
4480 * have the native byte order yet, and we don't have any
4481 * trace block yet, then fail with EINCOMPLETE.
4483 if (ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
4484 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4485 if (got_trace_decl
) {
4486 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
4491 ret
= set_trace_byte_order(ctx
, iter
);
4493 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
4494 "Cannot set trace's native byte order: "
4500 got_trace_decl
= true;
4503 if (!got_trace_decl
) {
4504 BT_CPPLOGD_STR_SPEC(ctx
->logger
, "Incomplete AST: need trace (`trace` block).");
4510 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_LITTLE
||
4511 ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_BIG
);
4512 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4515 bt_list_for_each_entry (iter
, &node
->u
.root
.env
, siblings
) {
4516 ret
= visit_env(ctx
, iter
);
4518 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4520 "Cannot visit trace's environment (`env` block) entry: "
4527 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4530 * Visit clock blocks.
4532 bt_list_for_each_entry (iter
, &node
->u
.root
.clock
, siblings
) {
4533 ret
= visit_clock_decl(ctx
, iter
);
4535 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit clock class: ret={}", ret
);
4540 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4543 * Visit root declarations next, as they can be used by any
4546 bt_list_for_each_entry (iter
, &node
->u
.root
.declaration_list
, siblings
) {
4547 ret
= visit_root_decl(ctx
, iter
);
4549 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit root entry: ret={}", ret
);
4554 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4556 /* Callsite blocks are not supported */
4557 bt_list_for_each_entry (iter
, &node
->u
.root
.callsite
, siblings
) {
4558 _BT_CPPLOGW_NODE(iter
, "\"callsite\" blocks are not supported as of this version.");
4561 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4564 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4565 ret
= visit_trace_decl(ctx
, iter
);
4567 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
4568 "Cannot visit trace (`trace` block): "
4575 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4578 bt_list_for_each_entry (iter
, &node
->u
.root
.stream
, siblings
) {
4579 ret
= visit_stream_decl(ctx
, iter
);
4581 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit stream class: ret={}", ret
);
4586 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4589 bt_list_for_each_entry (iter
, &node
->u
.root
.event
, siblings
) {
4590 ret
= visit_event_decl(ctx
, iter
);
4592 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit event class: ret={}", ret
);
4597 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4601 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Unexpected node type: node-type={}", node
->type
);
4606 /* Update default clock classes */
4607 ret
= ctf_trace_class_update_default_clock_classes(ctx
->ctf_tc
, ctx
->logger
);
4613 /* Update trace class meanings */
4614 ret
= ctf_trace_class_update_meanings(ctx
->ctf_tc
);
4620 /* Update stream class configuration */
4621 ret
= ctf_trace_class_update_stream_class_config(ctx
->ctf_tc
);
4627 /* Update text arrays and sequences */
4628 ret
= ctf_trace_class_update_text_array_sequence(ctx
->ctf_tc
);
4634 /* Update structure/array/sequence alignments */
4635 ret
= ctf_trace_class_update_alignments(ctx
->ctf_tc
);
4641 /* Resolve sequence lengths and variant tags */
4642 ret
= ctf_trace_class_resolve_field_classes(ctx
->ctf_tc
, ctx
->logger
);
4648 if (ctx
->trace_class
) {
4650 * Update "in IR" for field classes.
4652 * If we have no IR trace class, then we'll have no way
4653 * to create IR fields anyway, so we leave all the
4654 * `in_ir` members false.
4656 ret
= ctf_trace_class_update_in_ir(ctx
->ctf_tc
);
4663 /* Update saved value indexes */
4664 ret
= ctf_trace_class_update_value_storing_indexes(ctx
->ctf_tc
);
4670 /* Validate what we have so far */
4671 ret
= ctf_trace_class_validate(ctx
->ctf_tc
, ctx
->logger
);
4678 * If there are fields which are not related to the CTF format
4679 * itself in the packet header and in event header field
4680 * classes, warn about it because they are never translated.
4682 ctf_trace_class_warn_meaningless_header_fields(ctx
->ctf_tc
, ctx
->logger
);
4684 if (ctx
->trace_class
) {
4685 /* Copy new CTF metadata -> new IR metadata */
4687 ctf_trace_class_translate(ctx
->decoder_config
.self_comp
, ctx
->trace_class
, ctx
->ctf_tc
);