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 <babeltrace2/babeltrace.h>
15 #include "logging.hpp"
17 #include "common/assert.h"
18 #include "common/common.h"
19 #include "common/uuid.h"
20 #include "compat/endian.h" /* IWYU pragma: keep */
21 #include "cpp-common/bt2c/logging.hpp"
22 #include "cpp-common/bt2s/make-unique.hpp"
24 #include "../normalize-clk-offset.hpp"
26 #include "ctf-meta-visitors.hpp"
27 #include "ctf-meta.hpp"
29 /* Bit value (left shift) */
30 #define _BV(_val) (1 << (_val))
32 /* Bit is set in a set of bits */
33 #define _IS_SET(_set, _mask) (*(_set) & (_mask))
35 /* Set bit in a set of bits */
36 #define _SET(_set, _mask) (*(_set) |= (_mask))
38 /* Try to push scope, or go to the `error` label */
39 #define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
41 ret = ctx_push_scope(ctx); \
43 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx->logger, "Cannot push scope."); \
48 /* Bits for verifying existing attributes in various declarations */
51 _CLOCK_NAME_SET
= _BV(0),
52 _CLOCK_UUID_SET
= _BV(1),
53 _CLOCK_FREQ_SET
= _BV(2),
54 _CLOCK_PRECISION_SET
= _BV(3),
55 _CLOCK_OFFSET_S_SET
= _BV(4),
56 _CLOCK_OFFSET_SET
= _BV(5),
57 _CLOCK_ABSOLUTE_SET
= _BV(6),
58 _CLOCK_DESCRIPTION_SET
= _BV(7),
63 _INTEGER_ALIGN_SET
= _BV(0),
64 _INTEGER_SIZE_SET
= _BV(1),
65 _INTEGER_BASE_SET
= _BV(2),
66 _INTEGER_ENCODING_SET
= _BV(3),
67 _INTEGER_BYTE_ORDER_SET
= _BV(4),
68 _INTEGER_SIGNED_SET
= _BV(5),
69 _INTEGER_MAP_SET
= _BV(6),
74 _FLOAT_ALIGN_SET
= _BV(0),
75 _FLOAT_MANT_DIG_SET
= _BV(1),
76 _FLOAT_EXP_DIG_SET
= _BV(2),
77 _FLOAT_BYTE_ORDER_SET
= _BV(3),
82 _STRING_ENCODING_SET
= _BV(0),
87 _TRACE_MINOR_SET
= _BV(0),
88 _TRACE_MAJOR_SET
= _BV(1),
89 _TRACE_BYTE_ORDER_SET
= _BV(2),
90 _TRACE_UUID_SET
= _BV(3),
91 _TRACE_PACKET_HEADER_SET
= _BV(4),
96 _STREAM_ID_SET
= _BV(0),
97 _STREAM_PACKET_CONTEXT_SET
= _BV(1),
98 _STREAM_EVENT_HEADER_SET
= _BV(2),
99 _STREAM_EVENT_CONTEXT_SET
= _BV(3),
104 _EVENT_NAME_SET
= _BV(0),
105 _EVENT_ID_SET
= _BV(1),
106 _EVENT_MODEL_EMF_URI_SET
= _BV(2),
107 _EVENT_STREAM_ID_SET
= _BV(3),
108 _EVENT_LOG_LEVEL_SET
= _BV(4),
109 _EVENT_CONTEXT_SET
= _BV(5),
110 _EVENT_FIELDS_SET
= _BV(6),
119 LOG_LEVEL_WARNING
= 4,
120 LOG_LEVEL_NOTICE
= 5,
122 LOG_LEVEL_DEBUG_SYSTEM
= 7,
123 LOG_LEVEL_DEBUG_PROGRAM
= 8,
124 LOG_LEVEL_DEBUG_PROCESS
= 9,
125 LOG_LEVEL_DEBUG_MODULE
= 10,
126 LOG_LEVEL_DEBUG_UNIT
= 11,
127 LOG_LEVEL_DEBUG_FUNCTION
= 12,
128 LOG_LEVEL_DEBUG_LINE
= 13,
129 LOG_LEVEL_DEBUG
= 14,
133 /* Prefixes of class aliases */
134 #define _PREFIX_ALIAS 'a'
135 #define _PREFIX_ENUM 'e'
136 #define _PREFIX_STRUCT 's'
137 #define _PREFIX_VARIANT 'v'
139 /* First entry in a BT list */
140 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) bt_list_entry((_ptr)->next, _class, _member)
142 #define _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \
143 _BT_CPPLOGE_APPEND_CAUSE_LINENO(ctx->logger, (_node)->lineno, \
144 "Duplicate attribute in {}: attr-name=\"{}\"", _entity, _attr)
146 #define _BT_CPPLOGE_NODE(_node, _msg, args...) \
147 _BT_CPPLOGE_LINENO(ctx->logger, (_node)->lineno, _msg, ##args)
149 #define _BT_CPPLOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
150 _BT_CPPLOGE_APPEND_CAUSE_LINENO(ctx->logger, (_node)->lineno, _msg, ##args)
152 #define _BT_CPPLOGW_NODE(_node, _msg, args...) \
153 _BT_CPPLOGW_LINENO(ctx->logger, (_node)->lineno, _msg, ##args)
155 #define _BT_CPPLOGT_NODE(_node, _msg, args...) \
156 _BT_CPPLOGT_LINENO(ctx->logger, (_node)->lineno, _msg, ##args)
159 * Declaration scope of a visitor context. This represents a TSDL
160 * lexical scope, so that aliases and named structures, variants,
161 * and enumerations may be registered and looked up hierarchically.
163 struct ctx_decl_scope
166 * Alias name to field class.
168 * GQuark -> struct ctf_field_class * (owned by this)
170 GHashTable
*decl_map
;
172 /* Parent scope; NULL if this is the root declaration scope */
173 struct ctx_decl_scope
*parent_scope
;
177 * Creates a new declaration scope.
179 * @param par_scope Parent scope (NULL if creating a root scope)
180 * @returns New declaration scope, or NULL on error
182 static struct ctx_decl_scope
*ctx_decl_scope_create(struct ctf_visitor_generate_ir
*ctx
,
183 struct ctx_decl_scope
*par_scope
)
185 struct ctx_decl_scope
*scope
;
187 scope
= g_new(struct ctx_decl_scope
, 1);
189 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Failed to allocate one declaration scope.");
193 scope
->decl_map
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
,
194 (GDestroyNotify
) ctf_field_class_destroy
);
195 scope
->parent_scope
= par_scope
;
202 * Destroys a declaration scope.
204 * This function does not destroy the parent scope.
206 * @param scope Scope to destroy
208 static void ctx_decl_scope_destroy(struct ctx_decl_scope
*scope
)
214 g_hash_table_destroy(scope
->decl_map
);
222 * Returns the GQuark of a prefixed alias.
224 * @param prefix Prefix character
226 * @returns Associated GQuark, or 0 on error
228 static GQuark
get_prefixed_named_quark(char prefix
, const char *name
)
231 std::string prname
= std::string
{prefix
} + name
;
232 return g_quark_from_string(prname
.c_str());
236 * Looks up a prefixed class alias within a declaration scope.
238 * @param scope Declaration scope
239 * @param prefix Prefix character
240 * @param name Alias name
241 * @param levels Number of levels to dig into (-1 means infinite)
242 * @param copy True to return a copy
243 * @returns Declaration (owned by caller if \p copy is true),
244 * or NULL if not found
246 static struct ctf_field_class
*ctx_decl_scope_lookup_prefix_alias(struct ctx_decl_scope
*scope
,
247 char prefix
, const char *name
,
248 int levels
, bool copy
)
252 struct ctf_field_class
*decl
= NULL
;
253 struct ctx_decl_scope
*cur_scope
= scope
;
257 qname
= get_prefixed_named_quark(prefix
, name
);
266 while (cur_scope
&& cur_levels
< levels
) {
267 decl
= (ctf_field_class
*) g_hash_table_lookup(cur_scope
->decl_map
,
268 (gconstpointer
) GUINT_TO_POINTER(qname
));
270 /* Caller's reference */
272 decl
= ctf_field_class_copy(decl
);
279 cur_scope
= cur_scope
->parent_scope
;
288 * Looks up a class alias within a declaration scope.
290 * @param scope Declaration scope
291 * @param name Alias name
292 * @param levels Number of levels to dig into (-1 means infinite)
293 * @param copy True to return a copy
294 * @returns Declaration (owned by caller if \p copy is true),
295 * or NULL if not found
297 static struct ctf_field_class
*ctx_decl_scope_lookup_alias(struct ctx_decl_scope
*scope
,
298 const char *name
, int levels
, bool copy
)
300 return ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ALIAS
, name
, levels
, copy
);
304 * Looks up an enumeration within a declaration scope.
306 * @param scope Declaration scope
307 * @param name Enumeration name
308 * @param levels Number of levels to dig into (-1 means infinite)
309 * @param copy True to return a copy
310 * @returns Declaration (owned by caller if \p copy is true),
311 * or NULL if not found
313 static struct ctf_field_class_enum
*
314 ctx_decl_scope_lookup_enum(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
316 return ctf_field_class_as_enum(
317 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ENUM
, name
, levels
, copy
));
321 * Looks up a structure within a declaration scope.
323 * @param scope Declaration scope
324 * @param name Structure name
325 * @param levels Number of levels to dig into (-1 means infinite)
326 * @param copy True to return a copy
327 * @returns Declaration (owned by caller if \p copy is true),
328 * or NULL if not found
330 static struct ctf_field_class_struct
*
331 ctx_decl_scope_lookup_struct(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
333 return ctf_field_class_as_struct(
334 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_STRUCT
, name
, levels
, copy
));
338 * Looks up a variant within a declaration scope.
340 * @param scope Declaration scope
341 * @param name Variant name
342 * @param levels Number of levels to dig into (-1 means infinite)
343 * @param copy True to return a copy
344 * @returns Declaration (owned by caller if \p copy is true),
345 * or NULL if not found
347 static struct ctf_field_class_variant
*
348 ctx_decl_scope_lookup_variant(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
350 return ctf_field_class_as_variant(
351 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_VARIANT
, name
, levels
, copy
));
355 * Registers a prefixed class alias within a declaration scope.
357 * @param scope Declaration scope
358 * @param prefix Prefix character
359 * @param name Alias name (non-NULL)
360 * @param decl Field class to register (copied)
361 * @returns 0 if registration went okay, negative value otherwise
363 static int ctx_decl_scope_register_prefix_alias(struct ctx_decl_scope
*scope
, char prefix
,
364 const char *name
, struct ctf_field_class
*decl
)
372 qname
= get_prefixed_named_quark(prefix
, name
);
378 /* Make sure alias does not exist in local scope */
379 if (ctx_decl_scope_lookup_prefix_alias(scope
, prefix
, name
, 1, false)) {
384 decl
= ctf_field_class_copy(decl
);
386 g_hash_table_insert(scope
->decl_map
, GUINT_TO_POINTER(qname
), decl
);
393 * Registers a class alias within a declaration scope.
395 * @param scope Declaration scope
396 * @param name Alias name (non-NULL)
397 * @param decl Field class to register (copied)
398 * @returns 0 if registration went okay, negative value otherwise
400 static int ctx_decl_scope_register_alias(struct ctx_decl_scope
*scope
, const char *name
,
401 struct ctf_field_class
*decl
)
403 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ALIAS
, name
, decl
);
407 * Registers an enumeration declaration within a declaration scope.
409 * @param scope Declaration scope
410 * @param name Enumeration name (non-NULL)
411 * @param decl Enumeration field class to register (copied)
412 * @returns 0 if registration went okay, negative value otherwise
414 static int ctx_decl_scope_register_enum(struct ctx_decl_scope
*scope
, const char *name
,
415 struct ctf_field_class_enum
*decl
)
417 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ENUM
, name
, &decl
->base
.base
.base
);
421 * Registers a structure declaration within a declaration scope.
423 * @param scope Declaration scope
424 * @param name Structure name (non-NULL)
425 * @param decl Structure field class to register (copied)
426 * @returns 0 if registration went okay, negative value otherwise
428 static int ctx_decl_scope_register_struct(struct ctx_decl_scope
*scope
, const char *name
,
429 struct ctf_field_class_struct
*decl
)
431 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_STRUCT
, name
, &decl
->base
);
435 * Registers a variant declaration within a declaration scope.
437 * @param scope Declaration scope
438 * @param name Variant name (non-NULL)
439 * @param decl Variant field class to register
440 * @returns 0 if registration went okay, negative value otherwise
442 static int ctx_decl_scope_register_variant(struct ctx_decl_scope
*scope
, const char *name
,
443 struct ctf_field_class_variant
*decl
)
445 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_VARIANT
, name
, &decl
->base
);
448 ctf_visitor_generate_ir::~ctf_visitor_generate_ir()
450 struct ctx_decl_scope
*scope
= this->current_scope
;
453 * Destroy all scopes, from current one to the root scope.
456 struct ctx_decl_scope
*parent_scope
= scope
->parent_scope
;
458 ctx_decl_scope_destroy(scope
);
459 scope
= parent_scope
;
463 ctf_trace_class_destroy(this->ctf_tc
);
467 ctf_visitor_generate_ir::UP
ctf_visitor_generate_ir_create(const bt2c::Logger
& parentLogger
)
469 auto ctx
= bt2s::make_unique
<ctf_visitor_generate_ir
>(parentLogger
);
471 ctx
->ctf_tc
= ctf_trace_class_create();
473 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Cannot create CTF trace class.");
477 /* Root declaration scope */
478 ctx
->current_scope
= ctx_decl_scope_create(ctx
.get(), NULL
);
479 if (!ctx
->current_scope
) {
480 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Cannot create declaration scope.");
488 * Pushes a new declaration scope on top of a visitor context's
489 * declaration scope stack.
491 * @param ctx Visitor context
492 * @returns 0 on success, or a negative value on error
494 static int ctx_push_scope(struct ctf_visitor_generate_ir
*ctx
)
497 struct ctx_decl_scope
*new_scope
;
500 new_scope
= ctx_decl_scope_create(ctx
, ctx
->current_scope
);
502 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "Cannot create declaration scope.");
507 ctx
->current_scope
= new_scope
;
513 static void ctx_pop_scope(struct ctf_visitor_generate_ir
*ctx
)
515 struct ctx_decl_scope
*parent_scope
= NULL
;
519 if (!ctx
->current_scope
) {
523 parent_scope
= ctx
->current_scope
->parent_scope
;
524 ctx_decl_scope_destroy(ctx
->current_scope
);
525 ctx
->current_scope
= parent_scope
;
531 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
532 struct ctf_node
*ts_list
,
533 struct ctf_field_class
**decl
);
535 static int is_unary_string(struct bt_list_head
*head
)
538 struct ctf_node
*node
;
540 bt_list_for_each_entry (node
, head
, siblings
) {
541 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
545 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
553 static const char *get_map_clock_name_value(struct bt_list_head
*head
)
556 struct ctf_node
*node
;
557 const char *name
= NULL
;
559 bt_list_for_each_entry (node
, head
, siblings
) {
561 int uexpr_type
= node
->u
.unary_expression
.type
;
562 int uexpr_link
= node
->u
.unary_expression
.link
;
563 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_STRING
||
564 !((uexpr_link
!= UNARY_LINK_UNKNOWN
) ^ (i
== 0));
569 /* Needs to be chained with . */
570 switch (node
->u
.unary_expression
.link
) {
573 case UNARY_ARROWLINK
:
574 case UNARY_DOTDOTDOT
:
580 src_string
= node
->u
.unary_expression
.u
.string
;
584 if (strcmp("clock", src_string
)) {
592 if (strcmp("value", src_string
)) {
597 /* Extra identifier, unknown */
610 static int is_unary_unsigned(struct bt_list_head
*head
)
613 struct ctf_node
*node
;
615 bt_list_for_each_entry (node
, head
, siblings
) {
616 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
620 if (node
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
628 static int get_unary_unsigned(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
633 struct ctf_node
*node
;
637 if (bt_list_empty(head
)) {
642 bt_list_for_each_entry (node
, head
, siblings
) {
643 int uexpr_type
= node
->u
.unary_expression
.type
;
644 int uexpr_link
= node
->u
.unary_expression
.link
;
645 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_UNSIGNED_CONSTANT
||
646 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
648 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Invalid constant unsigned integer.");
653 *value
= node
->u
.unary_expression
.u
.unsigned_constant
;
661 static int is_unary_signed(struct bt_list_head
*head
)
664 struct ctf_node
*node
;
666 bt_list_for_each_entry (node
, head
, siblings
) {
667 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
671 if (node
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
) {
679 static int get_unary_signed(struct bt_list_head
*head
, int64_t *value
)
683 struct ctf_node
*node
;
685 bt_list_for_each_entry (node
, head
, siblings
) {
686 int uexpr_type
= node
->u
.unary_expression
.type
;
687 int uexpr_link
= node
->u
.unary_expression
.link
;
688 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
689 (uexpr_type
!= UNARY_UNSIGNED_CONSTANT
&& uexpr_type
!= UNARY_SIGNED_CONSTANT
) ||
690 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
696 switch (uexpr_type
) {
697 case UNARY_UNSIGNED_CONSTANT
:
698 *value
= (int64_t) node
->u
.unary_expression
.u
.unsigned_constant
;
700 case UNARY_SIGNED_CONSTANT
:
701 *value
= node
->u
.unary_expression
.u
.signed_constant
;
715 static int get_unary_uuid(struct bt_list_head
*head
, bt_uuid_t uuid
, const bt2c::Logger
& logger
)
717 return ctf_ast_get_unary_uuid(head
, uuid
, logger
);
720 static int get_boolean(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*unary_expr
)
724 if (unary_expr
->type
!= NODE_UNARY_EXPRESSION
) {
725 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr
, "Expecting unary expression: node-type={}",
731 switch (unary_expr
->u
.unary_expression
.type
) {
732 case UNARY_UNSIGNED_CONSTANT
:
733 ret
= (unary_expr
->u
.unary_expression
.u
.unsigned_constant
!= 0);
735 case UNARY_SIGNED_CONSTANT
:
736 ret
= (unary_expr
->u
.unary_expression
.u
.signed_constant
!= 0);
740 const char *str
= unary_expr
->u
.unary_expression
.u
.string
;
742 if (strcmp(str
, "true") == 0 || strcmp(str
, "TRUE") == 0) {
744 } else if (strcmp(str
, "false") == 0 || strcmp(str
, "FALSE") == 0) {
747 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr
, "Unexpected boolean value: value=\"{}\"",
755 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr
, "Unexpected unary expression type: node-type={}",
756 unary_expr
->u
.unary_expression
.type
);
765 static enum ctf_byte_order
byte_order_from_unary_expr(struct ctf_visitor_generate_ir
*ctx
,
766 struct ctf_node
*unary_expr
)
769 enum ctf_byte_order bo
= CTF_BYTE_ORDER_UNKNOWN
;
771 if (unary_expr
->u
.unary_expression
.type
!= UNARY_STRING
) {
772 _BT_CPPLOGE_APPEND_CAUSE_NODE(
773 unary_expr
, "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
777 str
= unary_expr
->u
.unary_expression
.u
.string
;
779 if (strcmp(str
, "be") == 0 || strcmp(str
, "network") == 0) {
780 bo
= CTF_BYTE_ORDER_BIG
;
781 } else if (strcmp(str
, "le") == 0) {
782 bo
= CTF_BYTE_ORDER_LITTLE
;
783 } else if (strcmp(str
, "native") == 0) {
784 bo
= CTF_BYTE_ORDER_DEFAULT
;
786 _BT_CPPLOGE_APPEND_CAUSE_NODE(unary_expr
,
787 "Unexpected \"byte_order\" attribute value: "
788 "expecting `be`, `le`, `network`, or `native`: value=\"{}\"",
797 static enum ctf_byte_order
get_real_byte_order(struct ctf_visitor_generate_ir
*ctx
,
798 struct ctf_node
*uexpr
)
800 enum ctf_byte_order bo
= byte_order_from_unary_expr(ctx
, uexpr
);
802 if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
803 bo
= ctx
->ctf_tc
->default_byte_order
;
809 static int is_align_valid(uint64_t align
)
811 return (align
!= 0) && !(align
& (align
- UINT64_C(1)));
814 static int get_class_specifier_name(struct ctf_visitor_generate_ir
*ctx
,
815 struct ctf_node
*cls_specifier
, GString
*str
)
819 if (cls_specifier
->type
!= NODE_TYPE_SPECIFIER
) {
820 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier
, "Unexpected node type: node-type={}",
821 cls_specifier
->type
);
826 switch (cls_specifier
->u
.field_class_specifier
.type
) {
828 g_string_append(str
, "void");
831 g_string_append(str
, "char");
834 g_string_append(str
, "short");
837 g_string_append(str
, "int");
840 g_string_append(str
, "long");
843 g_string_append(str
, "float");
845 case TYPESPEC_DOUBLE
:
846 g_string_append(str
, "double");
848 case TYPESPEC_SIGNED
:
849 g_string_append(str
, "signed");
851 case TYPESPEC_UNSIGNED
:
852 g_string_append(str
, "unsigned");
855 g_string_append(str
, "bool");
857 case TYPESPEC_COMPLEX
:
858 g_string_append(str
, "_Complex");
860 case TYPESPEC_IMAGINARY
:
861 g_string_append(str
, "_Imaginary");
864 g_string_append(str
, "const");
866 case TYPESPEC_ID_TYPE
:
867 if (cls_specifier
->u
.field_class_specifier
.id_type
) {
868 g_string_append(str
, cls_specifier
->u
.field_class_specifier
.id_type
);
871 case TYPESPEC_STRUCT
:
873 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
875 if (!node
->u
._struct
.name
) {
876 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty structure field class name.");
881 g_string_append(str
, "struct ");
882 g_string_append(str
, node
->u
._struct
.name
);
885 case TYPESPEC_VARIANT
:
887 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
889 if (!node
->u
.variant
.name
) {
890 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty variant field class name.");
895 g_string_append(str
, "variant ");
896 g_string_append(str
, node
->u
.variant
.name
);
901 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
903 if (!node
->u
._enum
.enum_id
) {
904 _BT_CPPLOGE_APPEND_CAUSE_NODE(
905 node
, "Unexpected empty enumeration field class (`enum`) name.");
910 g_string_append(str
, "enum ");
911 g_string_append(str
, node
->u
._enum
.enum_id
);
914 case TYPESPEC_FLOATING_POINT
:
915 case TYPESPEC_INTEGER
:
916 case TYPESPEC_STRING
:
918 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier
->u
.field_class_specifier
.node
,
919 "Unexpected field class specifier type: {}",
920 cls_specifier
->u
.field_class_specifier
.type
);
929 static int get_class_specifier_list_name(struct ctf_visitor_generate_ir
*ctx
,
930 struct ctf_node
*cls_specifier_list
, GString
*str
)
933 struct ctf_node
*iter
;
934 int alias_item_nr
= 0;
935 struct bt_list_head
*head
= &cls_specifier_list
->u
.field_class_specifier_list
.head
;
937 bt_list_for_each_entry (iter
, head
, siblings
) {
938 if (alias_item_nr
!= 0) {
939 g_string_append(str
, " ");
943 ret
= get_class_specifier_name(ctx
, iter
, str
);
953 static GQuark
create_class_alias_identifier(struct ctf_visitor_generate_ir
*ctx
,
954 struct ctf_node
*cls_specifier_list
,
955 struct ctf_node
*node_field_class_declarator
)
961 struct ctf_node
*iter
;
962 struct bt_list_head
*pointers
= &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
964 str
= g_string_new("");
965 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
967 g_string_free(str
, TRUE
);
971 bt_list_for_each_entry (iter
, pointers
, siblings
) {
972 g_string_append(str
, " *");
974 if (iter
->u
.pointer
.const_qualifier
) {
975 g_string_append(str
, " const");
979 str_c
= g_string_free(str
, FALSE
);
980 qalias
= g_quark_from_string(str_c
);
987 static int visit_field_class_declarator(struct ctf_visitor_generate_ir
*ctx
,
988 struct ctf_node
*cls_specifier_list
, GQuark
*field_name
,
989 struct ctf_node
*node_field_class_declarator
,
990 struct ctf_field_class
**field_decl
,
991 struct ctf_field_class
*nested_decl
)
994 * During this whole function, nested_decl is always OURS,
995 * whereas field_decl is an output which we create, but
996 * belongs to the caller (it is moved).
1001 /* Validate field class declarator node */
1002 if (node_field_class_declarator
) {
1003 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_UNKNOWN
) {
1004 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1005 node_field_class_declarator
, "Unexpected field class declarator type: type={}",
1006 node_field_class_declarator
->u
.field_class_declarator
.type
);
1011 /* TODO: GCC bitfields not supported yet */
1012 if (node_field_class_declarator
->u
.field_class_declarator
.bitfield_len
!= NULL
) {
1013 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1014 "GCC bitfields are not supported as of this version.");
1020 /* Find the right nested declaration if not provided */
1022 if (node_field_class_declarator
&&
1023 !bt_list_empty(&node_field_class_declarator
->u
.field_class_declarator
.pointers
)) {
1027 * If we have a pointer declarator, it HAS to
1028 * be present in the field class aliases (else
1032 create_class_alias_identifier(ctx
, cls_specifier_list
, node_field_class_declarator
);
1033 nested_decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, g_quark_to_string(qalias
),
1036 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1037 "Cannot find class alias: name=\"{}\"",
1038 g_quark_to_string(qalias
));
1043 if (nested_decl
->type
== CTF_FIELD_CLASS_TYPE_INT
) {
1044 /* Pointer: force integer's base to 16 */
1045 struct ctf_field_class_int
*int_fc
= ctf_field_class_as_int(nested_decl
);
1047 int_fc
->disp_base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
1050 ret
= visit_field_class_specifier_list(ctx
, cls_specifier_list
, &nested_decl
);
1052 BT_ASSERT(!nested_decl
);
1058 BT_ASSERT(nested_decl
);
1060 if (!node_field_class_declarator
) {
1061 *field_decl
= nested_decl
;
1066 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_ID
) {
1067 if (node_field_class_declarator
->u
.field_class_declarator
.u
.id
) {
1068 const char *id
= node_field_class_declarator
->u
.field_class_declarator
.u
.id
;
1070 *field_name
= g_quark_from_string(id
);
1075 *field_decl
= nested_decl
;
1079 struct ctf_node
*first
;
1080 struct ctf_field_class
*decl
= NULL
;
1081 struct ctf_field_class
*outer_field_decl
= NULL
;
1082 struct bt_list_head
*length
=
1083 &node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.length
;
1085 /* Create array/sequence, pass nested_decl as child */
1086 if (bt_list_empty(length
)) {
1087 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1088 "Expecting length field reference or value.");
1093 first
= _BT_LIST_FIRST_ENTRY(length
, struct ctf_node
, siblings
);
1094 if (first
->type
!= NODE_UNARY_EXPRESSION
) {
1095 _BT_CPPLOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type={}", first
->type
);
1100 switch (first
->u
.unary_expression
.type
) {
1101 case UNARY_UNSIGNED_CONSTANT
:
1103 struct ctf_field_class_array
*array_decl
= NULL
;
1105 array_decl
= ctf_field_class_array_create();
1106 BT_ASSERT(array_decl
);
1107 array_decl
->length
= first
->u
.unary_expression
.u
.unsigned_constant
;
1108 array_decl
->base
.elem_fc
= nested_decl
;
1110 decl
= &array_decl
->base
.base
;
1115 /* Lookup unsigned integer definition, create seq. */
1116 struct ctf_field_class_sequence
*seq_decl
= NULL
;
1117 char *length_name
= ctf_ast_concatenate_unary_strings(length
);
1120 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1121 "Cannot concatenate unary strings.");
1126 if (strncmp(length_name
, "env.", 4) == 0) {
1127 /* This is, in fact, an array */
1128 const char *env_entry_name
= &length_name
[4];
1129 struct ctf_trace_class_env_entry
*env_entry
=
1130 ctf_trace_class_borrow_env_entry_by_name(ctx
->ctf_tc
, env_entry_name
);
1131 struct ctf_field_class_array
*array_decl
;
1134 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1135 "Cannot find environment entry: "
1142 if (env_entry
->type
!= CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
) {
1143 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1144 "Wrong environment entry type "
1145 "(expecting integer): "
1152 if (env_entry
->value
.i
< 0) {
1153 _BT_CPPLOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1154 "Invalid, negative array length: "
1155 "env-entry-name=\"{}\", "
1157 env_entry_name
, env_entry
->value
.i
);
1162 array_decl
= ctf_field_class_array_create();
1163 BT_ASSERT(array_decl
);
1164 array_decl
->length
= (uint64_t) env_entry
->value
.i
;
1165 array_decl
->base
.elem_fc
= nested_decl
;
1167 decl
= &array_decl
->base
.base
;
1169 seq_decl
= ctf_field_class_sequence_create();
1170 BT_ASSERT(seq_decl
);
1171 seq_decl
->base
.elem_fc
= nested_decl
;
1173 g_string_assign(seq_decl
->length_ref
, length_name
);
1174 decl
= &seq_decl
->base
.base
;
1177 g_free(length_name
);
1185 BT_ASSERT(!nested_decl
);
1187 BT_ASSERT(!*field_decl
);
1190 * At this point, we found the next nested declaration.
1191 * We currently own this (and lost the ownership of
1192 * nested_decl in the meantime). Pass this next
1193 * nested declaration as the content of the outer
1194 * container, MOVING its ownership.
1196 ret
= visit_field_class_declarator(
1197 ctx
, cls_specifier_list
, field_name
,
1198 node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.field_class_declarator
,
1199 &outer_field_decl
, decl
);
1202 BT_ASSERT(!outer_field_decl
);
1207 BT_ASSERT(outer_field_decl
);
1208 *field_decl
= outer_field_decl
;
1209 outer_field_decl
= NULL
;
1212 BT_ASSERT(*field_decl
);
1216 ctf_field_class_destroy(*field_decl
);
1224 ctf_field_class_destroy(nested_decl
);
1229 static int visit_struct_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1230 struct ctf_field_class_struct
*struct_decl
,
1231 struct ctf_node
*cls_specifier_list
,
1232 struct bt_list_head
*field_class_declarators
)
1235 struct ctf_node
*iter
;
1236 struct ctf_field_class
*field_decl
= NULL
;
1238 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1241 const char *field_name
;
1243 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1246 BT_ASSERT(!field_decl
);
1247 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1248 "Cannot visit field class declarator: ret={}", ret
);
1252 BT_ASSERT(field_decl
);
1253 field_name
= g_quark_to_string(qfield_name
);
1255 /* Check if field with same name already exists */
1256 if (ctf_field_class_struct_borrow_member_by_name(struct_decl
, field_name
)) {
1257 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1258 "Duplicate field in structure field class: "
1259 "field-name=\"{}\"",
1265 /* Add field to structure */
1266 ctf_field_class_struct_append_member(struct_decl
, field_name
, field_decl
);
1273 ctf_field_class_destroy(field_decl
);
1278 static int visit_variant_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1279 struct ctf_field_class_variant
*variant_decl
,
1280 struct ctf_node
*cls_specifier_list
,
1281 struct bt_list_head
*field_class_declarators
)
1284 struct ctf_node
*iter
;
1285 struct ctf_field_class
*field_decl
= NULL
;
1287 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1290 const char *field_name
;
1292 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1295 BT_ASSERT(!field_decl
);
1296 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1297 "Cannot visit field class declarator: ret={}", ret
);
1301 BT_ASSERT(field_decl
);
1302 field_name
= g_quark_to_string(qfield_name
);
1304 /* Check if field with same name already exists */
1305 if (ctf_field_class_variant_borrow_option_by_name(variant_decl
, field_name
)) {
1306 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1307 "Duplicate field in variant field class: "
1308 "field-name=\"{}\"",
1314 /* Add field to structure */
1315 ctf_field_class_variant_append_option(variant_decl
, field_name
, field_decl
);
1322 ctf_field_class_destroy(field_decl
);
1327 static int visit_field_class_def(struct ctf_visitor_generate_ir
*ctx
,
1328 struct ctf_node
*cls_specifier_list
,
1329 struct bt_list_head
*field_class_declarators
)
1333 struct ctf_node
*iter
;
1334 struct ctf_field_class
*class_decl
= NULL
;
1336 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1337 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qidentifier
, iter
, &class_decl
,
1340 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit field class declarator: ret={}", ret
);
1345 /* Do not allow field class def and alias of untagged variants */
1346 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1347 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1349 if (var_fc
->tag_path
.path
->len
== 0) {
1350 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1351 iter
, "Type definition of untagged variant field class is not allowed.");
1357 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qidentifier
),
1360 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot register field class alias: name=\"{}\"",
1361 g_quark_to_string(qidentifier
));
1367 ctf_field_class_destroy(class_decl
);
1372 static int visit_field_class_alias(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*target
,
1373 struct ctf_node
*alias
)
1377 struct ctf_node
*node
;
1378 GQuark qdummy_field_name
;
1379 struct ctf_field_class
*class_decl
= NULL
;
1381 /* Create target field class */
1382 if (bt_list_empty(&target
->u
.field_class_alias_target
.field_class_declarators
)) {
1385 node
= _BT_LIST_FIRST_ENTRY(&target
->u
.field_class_alias_target
.field_class_declarators
,
1386 struct ctf_node
, siblings
);
1389 ret
= visit_field_class_declarator(
1390 ctx
, target
->u
.field_class_alias_target
.field_class_specifier_list
, &qdummy_field_name
,
1391 node
, &class_decl
, NULL
);
1393 BT_ASSERT(!class_decl
);
1394 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot visit field class declarator: ret={}", ret
);
1398 /* Do not allow field class def and alias of untagged variants */
1399 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1400 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1402 if (var_fc
->tag_path
.path
->len
== 0) {
1403 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1404 target
, "Type definition of untagged variant field class is not allowed.");
1411 * The semantic validator does not check whether the target is
1412 * abstract or not (if it has an identifier). Check it here.
1414 if (qdummy_field_name
!= 0) {
1415 _BT_CPPLOGE_APPEND_CAUSE_NODE(target
, "Expecting empty identifier: id=\"{}\"",
1416 g_quark_to_string(qdummy_field_name
));
1421 /* Create alias identifier */
1422 node
= _BT_LIST_FIRST_ENTRY(&alias
->u
.field_class_alias_name
.field_class_declarators
,
1423 struct ctf_node
, siblings
);
1424 qalias
= create_class_alias_identifier(
1425 ctx
, alias
->u
.field_class_alias_name
.field_class_specifier_list
, node
);
1426 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qalias
), class_decl
);
1428 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot register class alias: name=\"{}\"",
1429 g_quark_to_string(qalias
));
1434 ctf_field_class_destroy(class_decl
);
1439 static int visit_struct_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
1440 struct ctf_field_class_struct
*struct_decl
)
1444 switch (entry_node
->type
) {
1446 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1447 &entry_node
->u
.field_class_def
.field_class_declarators
);
1449 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1450 entry_node
, "Cannot add field class found in structure field class: ret={}", ret
);
1454 case NODE_TYPEALIAS
:
1455 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1456 entry_node
->u
.field_class_alias
.alias
);
1458 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1459 entry_node
, "Cannot add field class alias found in structure field class: ret={}",
1464 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1466 ret
= visit_struct_decl_field(
1468 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1469 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1475 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type={}",
1485 static int visit_variant_decl_entry(struct ctf_visitor_generate_ir
*ctx
,
1486 struct ctf_node
*entry_node
,
1487 struct ctf_field_class_variant
*variant_decl
)
1491 switch (entry_node
->type
) {
1493 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1494 &entry_node
->u
.field_class_def
.field_class_declarators
);
1496 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1497 entry_node
, "Cannot add field class found in variant field class: ret={}", ret
);
1501 case NODE_TYPEALIAS
:
1502 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1503 entry_node
->u
.field_class_alias
.alias
);
1505 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1506 entry_node
, "Cannot add field class alias found in variant field class: ret={}",
1511 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1513 ret
= visit_variant_decl_field(
1515 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1516 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1522 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type={}",
1532 static int visit_struct_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1533 struct bt_list_head
*decl_list
, int has_body
,
1534 struct bt_list_head
*min_align
,
1535 struct ctf_field_class_struct
**struct_decl
)
1539 BT_ASSERT(struct_decl
);
1540 *struct_decl
= NULL
;
1542 /* For named struct (without body), lookup in declaration scope */
1545 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1546 "Bodyless structure field class: missing name.");
1551 *struct_decl
= ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, -1, true);
1552 if (!*struct_decl
) {
1553 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1554 ctx
->logger
, "Cannot find structure field class: name=\"struct {}\"", name
);
1559 struct ctf_node
*entry_node
;
1560 uint64_t min_align_value
= 0;
1563 if (ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, 1, false)) {
1564 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1566 "Structure field class already declared in local scope: "
1567 "name=\"struct {}\"",
1574 if (!bt_list_empty(min_align
)) {
1575 ret
= get_unary_unsigned(ctx
, min_align
, &min_align_value
);
1577 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1579 "Unexpected unary expression for structure field class's `align` attribute: "
1586 *struct_decl
= ctf_field_class_struct_create();
1587 BT_ASSERT(*struct_decl
);
1589 if (min_align_value
!= 0) {
1590 (*struct_decl
)->base
.alignment
= min_align_value
;
1593 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1595 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1596 ret
= visit_struct_decl_entry(ctx
, entry_node
, *struct_decl
);
1598 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
,
1599 "Cannot visit structure field class entry: "
1610 ret
= ctx_decl_scope_register_struct(ctx
->current_scope
, name
, *struct_decl
);
1612 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1614 "Cannot register structure field class in declaration scope: "
1615 "name=\"struct {}\", ret={}",
1625 ctf_field_class_destroy(&(*struct_decl
)->base
);
1626 *struct_decl
= NULL
;
1630 static int visit_variant_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1631 const char *tag
, struct bt_list_head
*decl_list
, int has_body
,
1632 struct ctf_field_class_variant
**variant_decl
)
1635 struct ctf_field_class_variant
*untagged_variant_decl
= NULL
;
1637 BT_ASSERT(variant_decl
);
1638 *variant_decl
= NULL
;
1640 /* For named variant (without body), lookup in declaration scope */
1643 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1644 "Bodyless variant field class: missing name.");
1649 untagged_variant_decl
= ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, -1, true);
1650 if (!untagged_variant_decl
) {
1651 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1652 ctx
->logger
, "Cannot find variant field class: name=\"variant {}\"", name
);
1657 struct ctf_node
*entry_node
;
1660 if (ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, 1, false)) {
1661 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1662 "Variant field class already declared in local scope: "
1663 "name=\"variant {}\"",
1670 untagged_variant_decl
= ctf_field_class_variant_create();
1671 BT_ASSERT(untagged_variant_decl
);
1672 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1674 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1675 ret
= visit_variant_decl_entry(ctx
, entry_node
, untagged_variant_decl
);
1677 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
,
1678 "Cannot visit variant field class entry: "
1689 ret
= ctx_decl_scope_register_variant(ctx
->current_scope
, name
, untagged_variant_decl
);
1691 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1693 "Cannot register variant field class in declaration scope: "
1694 "name=\"variant {}\", ret={}",
1702 * If tagged, create tagged variant and return; otherwise
1703 * return untagged variant.
1706 *variant_decl
= untagged_variant_decl
;
1707 untagged_variant_decl
= NULL
;
1710 * At this point, we have a fresh untagged variant; nobody
1711 * else owns it. Set its tag now.
1713 g_string_assign(untagged_variant_decl
->tag_ref
, tag
);
1714 *variant_decl
= untagged_variant_decl
;
1715 untagged_variant_decl
= NULL
;
1718 BT_ASSERT(!untagged_variant_decl
);
1719 BT_ASSERT(*variant_decl
);
1723 ctf_field_class_destroy(&untagged_variant_decl
->base
);
1724 untagged_variant_decl
= NULL
;
1725 ctf_field_class_destroy(&(*variant_decl
)->base
);
1726 *variant_decl
= NULL
;
1740 static int visit_enum_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*enumerator
,
1741 struct ctf_field_class_enum
*enum_decl
, struct uori
*last
)
1745 struct ctf_node
*iter
;
1746 struct uori start
= {
1760 const char *label
= enumerator
->u
.enumerator
.id
;
1761 struct bt_list_head
*values
= &enumerator
->u
.enumerator
.values
;
1763 bt_list_for_each_entry (iter
, values
, siblings
) {
1764 struct uori
*target
;
1766 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
1767 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
1768 "Wrong expression for enumeration field class label: "
1769 "node-type={}, label=\"{}\"",
1781 switch (iter
->u
.unary_expression
.type
) {
1782 case UNARY_SIGNED_CONSTANT
:
1783 target
->is_signed
= true;
1784 target
->value
.i
= iter
->u
.unary_expression
.u
.signed_constant
;
1786 case UNARY_UNSIGNED_CONSTANT
:
1787 target
->is_signed
= false;
1788 target
->value
.u
= iter
->u
.unary_expression
.u
.unsigned_constant
;
1791 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
1792 "Invalid enumeration field class entry: "
1793 "expecting constant signed or unsigned integer: "
1794 "node-type={}, label=\"{}\"",
1795 iter
->u
.unary_expression
.type
, label
);
1801 _BT_CPPLOGE_APPEND_CAUSE_NODE(
1802 iter
, "Invalid enumeration field class entry: label=\"{}\"", label
);
1818 if (end
.is_signed
) {
1819 last
->value
.i
= end
.value
.i
+ 1;
1821 last
->value
.u
= end
.value
.u
+ 1;
1824 ctf_field_class_enum_map_range(enum_decl
, label
, start
.value
.u
, end
.value
.u
);
1831 static int visit_enum_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1832 struct ctf_node
*container_cls
, struct bt_list_head
*enumerator_list
,
1833 int has_body
, struct ctf_field_class_enum
**enum_decl
)
1837 struct ctf_field_class_int
*integer_decl
= NULL
;
1839 BT_ASSERT(enum_decl
);
1842 /* For named enum (without body), lookup in declaration scope */
1845 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1846 "Bodyless enumeration field class: missing name.");
1851 *enum_decl
= ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, -1, true);
1853 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
1854 "Cannot find enumeration field class: "
1861 struct ctf_node
*iter
;
1862 struct uori last_value
= {
1871 if (ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, 1, false)) {
1872 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1874 "Enumeration field class already declared in local scope: "
1882 if (!container_cls
) {
1883 integer_decl
= ctf_field_class_as_int(
1884 ctx_decl_scope_lookup_alias(ctx
->current_scope
, "int", -1, true));
1885 if (!integer_decl
) {
1886 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1888 "Cannot find implicit `int` field class alias for enumeration field class.");
1893 ctf_field_class
*decl
;
1895 ret
= visit_field_class_declarator(ctx
, container_cls
, &qdummy_id
, NULL
, &decl
, NULL
);
1902 integer_decl
= ctf_field_class_as_int(decl
);
1905 BT_ASSERT(integer_decl
);
1907 if (integer_decl
->base
.base
.type
!= CTF_FIELD_CLASS_TYPE_INT
) {
1908 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1910 "Container field class for enumeration field class is not an integer field class: "
1912 integer_decl
->base
.base
.type
);
1917 *enum_decl
= ctf_field_class_enum_create();
1918 BT_ASSERT(*enum_decl
);
1919 (*enum_decl
)->base
.base
.base
.alignment
= integer_decl
->base
.base
.alignment
;
1920 ctf_field_class_int_copy_content(&(*enum_decl
)->base
, integer_decl
);
1921 last_value
.is_signed
= (*enum_decl
)->base
.is_signed
;
1923 bt_list_for_each_entry (iter
, enumerator_list
, siblings
) {
1924 ret
= visit_enum_decl_entry(ctx
, iter
, *enum_decl
, &last_value
);
1926 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
1927 "Cannot visit enumeration field class entry: "
1935 ret
= ctx_decl_scope_register_enum(ctx
->current_scope
, name
, *enum_decl
);
1937 BT_CPPLOGE_APPEND_CAUSE_SPEC(
1939 "Cannot register enumeration field class in declaration scope: "
1950 ctf_field_class_destroy(&(*enum_decl
)->base
.base
.base
);
1954 ctf_field_class_destroy(&integer_decl
->base
.base
);
1955 integer_decl
= NULL
;
1959 static int visit_field_class_specifier(struct ctf_visitor_generate_ir
*ctx
,
1960 struct ctf_node
*cls_specifier_list
,
1961 struct ctf_field_class
**decl
)
1964 GString
*str
= NULL
;
1967 str
= g_string_new("");
1968 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
1970 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1971 "Cannot get field class specifier list's name: ret={}", ret
);
1975 *decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, str
->str
, -1, true);
1977 _BT_CPPLOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1978 "Cannot find field class alias: name=\"{}\"", str
->str
);
1986 ctf_field_class_destroy(*decl
);
1991 g_string_free(str
, TRUE
);
1997 static int visit_integer_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
1998 struct ctf_field_class_int
**integer_decl
)
2003 struct ctf_node
*expression
;
2004 uint64_t alignment
= 0, size
= 0;
2005 struct ctf_clock_class
*mapped_clock_class
= NULL
;
2006 enum ctf_encoding encoding
= CTF_ENCODING_NONE
;
2007 bt_field_class_integer_preferred_display_base base
=
2008 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2009 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2011 *integer_decl
= NULL
;
2013 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2014 struct ctf_node
*left
, *right
;
2016 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2018 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2020 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2021 _BT_CPPLOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type={}",
2022 left
->u
.unary_expression
.type
);
2027 if (strcmp(left
->u
.unary_expression
.u
.string
, "signed") == 0) {
2028 if (_IS_SET(&set
, _INTEGER_SIGNED_SET
)) {
2029 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "signed", "integer field class");
2034 signedness
= get_boolean(ctx
, right
);
2035 if (signedness
< 0) {
2036 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2038 "Invalid boolean value for integer field class's `signed` attribute: "
2045 _SET(&set
, _INTEGER_SIGNED_SET
);
2046 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2047 if (_IS_SET(&set
, _INTEGER_BYTE_ORDER_SET
)) {
2048 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order", "integer field class");
2053 byte_order
= get_real_byte_order(ctx
, right
);
2054 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2055 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2057 "Invalid `byte_order` attribute in integer field class: "
2064 _SET(&set
, _INTEGER_BYTE_ORDER_SET
);
2065 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "size") == 0) {
2066 if (_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2067 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "size", "integer field class");
2072 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2073 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2074 "Invalid `size` attribute in integer field class: "
2075 "expecting unsigned constant integer: "
2077 right
->u
.unary_expression
.type
);
2082 size
= right
->u
.unary_expression
.u
.unsigned_constant
;
2084 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2085 "Invalid `size` attribute in integer field class: "
2086 "expecting positive constant integer: "
2091 } else if (size
> 64) {
2092 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2094 "Invalid `size` attribute in integer field class: "
2095 "integer fields over 64 bits are not supported as of this version: "
2102 _SET(&set
, _INTEGER_SIZE_SET
);
2103 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2104 if (_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2105 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "align", "integer field class");
2110 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2111 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2112 "Invalid `align` attribute in integer field class: "
2113 "expecting unsigned constant integer: "
2115 right
->u
.unary_expression
.type
);
2120 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2121 if (!is_align_valid(alignment
)) {
2122 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2123 "Invalid `align` attribute in integer field class: "
2124 "expecting power of two: "
2131 _SET(&set
, _INTEGER_ALIGN_SET
);
2132 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "base") == 0) {
2133 if (_IS_SET(&set
, _INTEGER_BASE_SET
)) {
2134 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "base", "integer field class");
2139 switch (right
->u
.unary_expression
.type
) {
2140 case UNARY_UNSIGNED_CONSTANT
:
2142 uint64_t constant
= right
->u
.unary_expression
.u
.unsigned_constant
;
2146 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2149 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2152 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2155 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2158 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2160 "Invalid `base` attribute in integer field class: "
2162 right
->u
.unary_expression
.u
.unsigned_constant
);
2171 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2173 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2175 "Unexpected unary expression for integer field class's `base` attribute.");
2180 if (strcmp(s_right
, "decimal") == 0 || strcmp(s_right
, "dec") == 0 ||
2181 strcmp(s_right
, "d") == 0 || strcmp(s_right
, "i") == 0 ||
2182 strcmp(s_right
, "u") == 0) {
2183 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2184 } else if (strcmp(s_right
, "hexadecimal") == 0 || strcmp(s_right
, "hex") == 0 ||
2185 strcmp(s_right
, "x") == 0 || strcmp(s_right
, "X") == 0 ||
2186 strcmp(s_right
, "p") == 0) {
2187 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2188 } else if (strcmp(s_right
, "octal") == 0 || strcmp(s_right
, "oct") == 0 ||
2189 strcmp(s_right
, "o") == 0) {
2190 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2191 } else if (strcmp(s_right
, "binary") == 0 || strcmp(s_right
, "b") == 0) {
2192 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2194 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2196 "Unexpected unary expression for integer field class's `base` attribute: "
2208 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2209 right
, "Invalid `base` attribute in integer field class: "
2210 "expecting unsigned constant integer or unary string.");
2215 _SET(&set
, _INTEGER_BASE_SET
);
2216 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2219 if (_IS_SET(&set
, _INTEGER_ENCODING_SET
)) {
2220 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "integer field class");
2225 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2226 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2227 right
, "Invalid `encoding` attribute in integer field class: "
2228 "expecting unary string.");
2233 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2235 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2237 "Unexpected unary expression for integer field class's `encoding` attribute.");
2242 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2243 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2244 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2245 encoding
= CTF_ENCODING_UTF8
;
2246 } else if (strcmp(s_right
, "none") == 0) {
2247 encoding
= CTF_ENCODING_NONE
;
2249 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2251 "Invalid `encoding` attribute in integer field class: "
2252 "unknown encoding: encoding=\"{}\"",
2260 _SET(&set
, _INTEGER_ENCODING_SET
);
2261 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "map") == 0) {
2262 const char *clock_name
;
2264 if (_IS_SET(&set
, _INTEGER_MAP_SET
)) {
2265 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "map", "integer field class");
2270 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2271 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2272 "Invalid `map` attribute in integer field class: "
2273 "expecting unary string.");
2278 clock_name
= get_map_clock_name_value(&expression
->u
.ctf_expression
.right
);
2281 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2284 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2286 "Unexpected unary expression for integer field class's `map` attribute.");
2291 _BT_CPPLOGE_NODE(right
,
2292 "Invalid `map` attribute in integer field class: "
2293 "cannot find clock class at this point: name=\"{}\"",
2295 _SET(&set
, _INTEGER_MAP_SET
);
2300 mapped_clock_class
=
2301 ctf_trace_class_borrow_clock_class_by_name(ctx
->ctf_tc
, clock_name
);
2302 if (!mapped_clock_class
) {
2303 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2304 "Invalid `map` attribute in integer field class: "
2305 "cannot find clock class at this point: name=\"{}\"",
2311 _SET(&set
, _INTEGER_MAP_SET
);
2313 _BT_CPPLOGW_NODE(left
,
2314 "Unknown attribute in integer field class: "
2316 left
->u
.unary_expression
.u
.string
);
2320 if (!_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2321 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
2322 "Missing `size` attribute in integer field class.");
2327 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2328 if (size
% CHAR_BIT
) {
2329 /* Bit-packed alignment */
2332 /* Byte-packed alignment */
2333 alignment
= CHAR_BIT
;
2337 *integer_decl
= ctf_field_class_int_create();
2338 BT_ASSERT(*integer_decl
);
2339 (*integer_decl
)->base
.base
.alignment
= alignment
;
2340 (*integer_decl
)->base
.byte_order
= byte_order
;
2341 (*integer_decl
)->base
.size
= size
;
2342 (*integer_decl
)->is_signed
= (signedness
> 0);
2343 (*integer_decl
)->disp_base
= base
;
2344 (*integer_decl
)->encoding
= encoding
;
2345 (*integer_decl
)->mapped_clock_class
= mapped_clock_class
;
2349 ctf_field_class_destroy(&(*integer_decl
)->base
.base
);
2350 *integer_decl
= NULL
;
2354 static int visit_floating_point_number_decl(struct ctf_visitor_generate_ir
*ctx
,
2355 struct bt_list_head
*expressions
,
2356 struct ctf_field_class_float
**float_decl
)
2360 struct ctf_node
*expression
;
2361 uint64_t alignment
= 1, exp_dig
= 0, mant_dig
= 0;
2362 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2366 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2367 struct ctf_node
*left
, *right
;
2369 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2371 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2373 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2374 _BT_CPPLOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type={}",
2375 left
->u
.unary_expression
.type
);
2380 if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2381 if (_IS_SET(&set
, _FLOAT_BYTE_ORDER_SET
)) {
2382 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order",
2383 "floating point number field class");
2388 byte_order
= get_real_byte_order(ctx
, right
);
2389 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2390 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2392 "Invalid `byte_order` attribute in floating point number field class: "
2399 _SET(&set
, _FLOAT_BYTE_ORDER_SET
);
2400 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "exp_dig") == 0) {
2401 if (_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2402 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "exp_dig",
2403 "floating point number field class");
2408 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2409 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2411 "Invalid `exp_dig` attribute in floating point number field class: "
2412 "expecting unsigned constant integer: "
2414 right
->u
.unary_expression
.type
);
2419 exp_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2420 _SET(&set
, _FLOAT_EXP_DIG_SET
);
2421 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "mant_dig") == 0) {
2422 if (_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2423 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "mant_dig",
2424 "floating point number field class");
2429 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2430 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2432 "Invalid `mant_dig` attribute in floating point number field class: "
2433 "expecting unsigned constant integer: "
2435 right
->u
.unary_expression
.type
);
2440 mant_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2441 _SET(&set
, _FLOAT_MANT_DIG_SET
);
2442 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2443 if (_IS_SET(&set
, _FLOAT_ALIGN_SET
)) {
2444 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "align",
2445 "floating point number field class");
2450 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2451 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2453 "Invalid `align` attribute in floating point number field class: "
2454 "expecting unsigned constant integer: "
2456 right
->u
.unary_expression
.type
);
2461 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2463 if (!is_align_valid(alignment
)) {
2464 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2466 "Invalid `align` attribute in floating point number field class: "
2467 "expecting power of two: "
2474 _SET(&set
, _FLOAT_ALIGN_SET
);
2476 _BT_CPPLOGW_NODE(left
,
2477 "Unknown attribute in floating point number field class: "
2479 left
->u
.unary_expression
.u
.string
);
2483 if (!_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2484 BT_CPPLOGE_APPEND_CAUSE_SPEC(
2485 ctx
->logger
, "Missing `mant_dig` attribute in floating point number field class.");
2490 if (!_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2491 BT_CPPLOGE_APPEND_CAUSE_SPEC(
2492 ctx
->logger
, "Missing `exp_dig` attribute in floating point number field class.");
2497 if (mant_dig
!= 24 && mant_dig
!= 53) {
2498 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
, "`mant_dig` attribute: expecting 24 or 53.");
2503 if (mant_dig
== 24 && exp_dig
!= 8) {
2504 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
2505 "`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2510 if (mant_dig
== 53 && exp_dig
!= 11) {
2511 BT_CPPLOGE_APPEND_CAUSE_SPEC(ctx
->logger
,
2512 "`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2517 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2518 if ((mant_dig
+ exp_dig
) % CHAR_BIT
) {
2519 /* Bit-packed alignment */
2522 /* Byte-packed alignment */
2523 alignment
= CHAR_BIT
;
2527 *float_decl
= ctf_field_class_float_create();
2528 BT_ASSERT(*float_decl
);
2529 (*float_decl
)->base
.base
.alignment
= alignment
;
2530 (*float_decl
)->base
.byte_order
= byte_order
;
2531 (*float_decl
)->base
.size
= mant_dig
+ exp_dig
;
2535 ctf_field_class_destroy(&(*float_decl
)->base
.base
);
2540 static int visit_string_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2541 struct ctf_field_class_string
**string_decl
)
2545 struct ctf_node
*expression
;
2547 *string_decl
= NULL
;
2549 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2550 struct ctf_node
*left
, *right
;
2552 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2554 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2556 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2557 _BT_CPPLOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type={}",
2558 left
->u
.unary_expression
.type
);
2563 if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2566 if (_IS_SET(&set
, _STRING_ENCODING_SET
)) {
2567 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "string field class");
2572 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2573 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2574 "Invalid `encoding` attribute in string field class: "
2575 "expecting unary string.");
2580 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2582 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2584 "Unexpected unary expression for string field class's `encoding` attribute.");
2589 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2590 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2591 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2593 } else if (strcmp(s_right
, "none") == 0) {
2596 _BT_CPPLOGE_APPEND_CAUSE_NODE(right
,
2597 "Invalid `encoding` attribute in string field class: "
2598 "unknown encoding: encoding=\"{}\"",
2606 _SET(&set
, _STRING_ENCODING_SET
);
2608 _BT_CPPLOGW_NODE(left
,
2609 "Unknown attribute in string field class: "
2611 left
->u
.unary_expression
.u
.string
);
2615 *string_decl
= ctf_field_class_string_create();
2616 BT_ASSERT(*string_decl
);
2620 ctf_field_class_destroy(&(*string_decl
)->base
);
2621 *string_decl
= NULL
;
2625 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
2626 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
)
2629 struct ctf_node
*first
, *node
;
2633 if (ts_list
->type
!= NODE_TYPE_SPECIFIER_LIST
) {
2634 _BT_CPPLOGE_APPEND_CAUSE_NODE(ts_list
, "Unexpected node type: node-type={}", ts_list
->type
);
2639 first
= _BT_LIST_FIRST_ENTRY(&ts_list
->u
.field_class_specifier_list
.head
, struct ctf_node
,
2641 if (first
->type
!= NODE_TYPE_SPECIFIER
) {
2642 _BT_CPPLOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type={}", first
->type
);
2647 node
= first
->u
.field_class_specifier
.node
;
2649 switch (first
->u
.field_class_specifier
.type
) {
2650 case TYPESPEC_INTEGER
:
2652 ctf_field_class_int
*int_decl
;
2654 ret
= visit_integer_decl(ctx
, &node
->u
.integer
.expressions
, &int_decl
);
2656 BT_ASSERT(!int_decl
);
2660 *decl
= &int_decl
->base
.base
;
2663 case TYPESPEC_FLOATING_POINT
:
2665 ctf_field_class_float
*float_decl
;
2668 visit_floating_point_number_decl(ctx
, &node
->u
.floating_point
.expressions
, &float_decl
);
2670 BT_ASSERT(!float_decl
);
2674 *decl
= &float_decl
->base
.base
;
2677 case TYPESPEC_STRING
:
2679 ctf_field_class_string
*string_decl
;
2681 ret
= visit_string_decl(ctx
, &node
->u
.string
.expressions
, &string_decl
);
2683 BT_ASSERT(!string_decl
);
2687 *decl
= &string_decl
->base
;
2690 case TYPESPEC_STRUCT
:
2692 ctf_field_class_struct
*struct_decl
;
2694 ret
= visit_struct_decl(ctx
, node
->u
._struct
.name
, &node
->u
._struct
.declaration_list
,
2695 node
->u
._struct
.has_body
, &node
->u
._struct
.min_align
, &struct_decl
);
2697 BT_ASSERT(!struct_decl
);
2701 *decl
= &struct_decl
->base
;
2704 case TYPESPEC_VARIANT
:
2706 ctf_field_class_variant
*variant_decl
;
2708 ret
= visit_variant_decl(ctx
, node
->u
.variant
.name
, node
->u
.variant
.choice
,
2709 &node
->u
.variant
.declaration_list
, node
->u
.variant
.has_body
,
2712 BT_ASSERT(!variant_decl
);
2716 *decl
= &variant_decl
->base
;
2721 ctf_field_class_enum
*enum_decl
;
2723 ret
= visit_enum_decl(ctx
, node
->u
._enum
.enum_id
, node
->u
._enum
.container_field_class
,
2724 &node
->u
._enum
.enumerator_list
, node
->u
._enum
.has_body
, &enum_decl
);
2726 BT_ASSERT(!enum_decl
);
2730 *decl
= &enum_decl
->base
.base
.base
;
2735 case TYPESPEC_SHORT
:
2738 case TYPESPEC_FLOAT
:
2739 case TYPESPEC_DOUBLE
:
2740 case TYPESPEC_SIGNED
:
2741 case TYPESPEC_UNSIGNED
:
2743 case TYPESPEC_COMPLEX
:
2744 case TYPESPEC_IMAGINARY
:
2745 case TYPESPEC_CONST
:
2746 case TYPESPEC_ID_TYPE
:
2747 ret
= visit_field_class_specifier(ctx
, ts_list
, decl
);
2749 _BT_CPPLOGE_APPEND_CAUSE_NODE(first
, "Cannot visit field class specifier: ret={}", ret
);
2755 _BT_CPPLOGE_APPEND_CAUSE_NODE(first
, "Unexpected field class specifier type: node-type={}",
2756 first
->u
.field_class_specifier
.type
);
2765 ctf_field_class_destroy(*decl
);
2770 static int visit_event_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
2771 struct ctf_event_class
*event_class
, uint64_t *stream_id
,
2777 switch (node
->type
) {
2779 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
2780 &node
->u
.field_class_def
.field_class_declarators
);
2782 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in event class.");
2786 case NODE_TYPEALIAS
:
2787 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
2788 node
->u
.field_class_alias
.alias
);
2790 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
2791 "Cannot add field class alias found in event class.");
2795 case NODE_CTF_EXPRESSION
:
2797 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
2799 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
2804 if (strcmp(left
, "name") == 0) {
2805 /* This is already known at this stage */
2806 if (_IS_SET(set
, _EVENT_NAME_SET
)) {
2807 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "name", "event class");
2812 _SET(set
, _EVENT_NAME_SET
);
2813 } else if (strcmp(left
, "id") == 0) {
2816 if (_IS_SET(set
, _EVENT_ID_SET
)) {
2817 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "event class");
2822 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
2823 /* Only read "id" if get_unary_unsigned() succeeded. */
2824 if (ret
|| (!ret
&& id
< 0)) {
2825 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2826 node
, "Unexpected unary expression for event class's `id` attribute.");
2831 event_class
->id
= id
;
2832 _SET(set
, _EVENT_ID_SET
);
2833 } else if (strcmp(left
, "stream_id") == 0) {
2834 if (_IS_SET(set
, _EVENT_STREAM_ID_SET
)) {
2835 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "stream_id", "event class");
2840 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, stream_id
);
2843 * Only read "stream_id" if get_unary_unsigned()
2847 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2848 node
, "Unexpected unary expression for event class's `stream_id` attribute.");
2853 _SET(set
, _EVENT_STREAM_ID_SET
);
2854 } else if (strcmp(left
, "context") == 0) {
2855 if (_IS_SET(set
, _EVENT_CONTEXT_SET
)) {
2856 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate `context` entry in event class.");
2861 ret
= visit_field_class_specifier_list(
2862 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2863 &event_class
->spec_context_fc
);
2865 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
2866 "Cannot create event class's context field class.");
2870 BT_ASSERT(event_class
->spec_context_fc
);
2871 _SET(set
, _EVENT_CONTEXT_SET
);
2872 } else if (strcmp(left
, "fields") == 0) {
2873 if (_IS_SET(set
, _EVENT_FIELDS_SET
)) {
2874 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate `fields` entry in event class.");
2879 ret
= visit_field_class_specifier_list(
2880 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2881 &event_class
->payload_fc
);
2883 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
2884 "Cannot create event class's payload field class.");
2888 BT_ASSERT(event_class
->payload_fc
);
2889 _SET(set
, _EVENT_FIELDS_SET
);
2890 } else if (strcmp(left
, "loglevel") == 0) {
2891 uint64_t loglevel_value
;
2892 bool is_log_level_known
= true;
2893 bt_event_class_log_level log_level
;
2895 if (_IS_SET(set
, _EVENT_LOG_LEVEL_SET
)) {
2896 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "loglevel", "event class");
2901 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &loglevel_value
);
2903 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2904 node
, "Unexpected unary expression for event class's `loglevel` attribute.");
2909 switch (loglevel_value
) {
2911 log_level
= BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
;
2914 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ALERT
;
2917 log_level
= BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
;
2920 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ERROR
;
2923 log_level
= BT_EVENT_CLASS_LOG_LEVEL_WARNING
;
2926 log_level
= BT_EVENT_CLASS_LOG_LEVEL_NOTICE
;
2929 log_level
= BT_EVENT_CLASS_LOG_LEVEL_INFO
;
2932 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
;
2935 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
;
2938 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
;
2941 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
;
2944 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
;
2947 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
;
2950 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
;
2953 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG
;
2956 is_log_level_known
= false;
2959 "Not setting event class's log level because its value is unknown: "
2964 if (is_log_level_known
) {
2965 ctf_event_class_set_log_level(event_class
, log_level
);
2968 _SET(set
, _EVENT_LOG_LEVEL_SET
);
2969 } else if (strcmp(left
, "model.emf.uri") == 0) {
2972 if (_IS_SET(set
, _EVENT_MODEL_EMF_URI_SET
)) {
2973 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "model.emf.uri", "event class");
2978 right
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.right
);
2980 _BT_CPPLOGE_APPEND_CAUSE_NODE(
2982 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
2987 if (strlen(right
) == 0) {
2988 _BT_CPPLOGW_NODE(node
, "Not setting event class's EMF URI because it's empty.");
2990 g_string_assign(event_class
->emf_uri
, right
);
2994 _SET(set
, _EVENT_MODEL_EMF_URI_SET
);
2996 _BT_CPPLOGW_NODE(node
,
2997 "Unknown attribute in event class: "
3020 static char *get_event_decl_name(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3024 struct ctf_node
*iter
;
3025 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3027 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3028 if (iter
->type
!= NODE_CTF_EXPRESSION
) {
3032 left
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.left
);
3034 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot concatenate unary strings.");
3038 if (strcmp(left
, "name") == 0) {
3039 name
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.right
);
3041 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3042 iter
, "Unexpected unary expression for event class's `name` attribute.");
3062 static int visit_event_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3066 struct ctf_node
*iter
;
3067 uint64_t stream_id
= 0;
3068 char *event_name
= NULL
;
3069 struct ctf_event_class
*event_class
= NULL
;
3070 struct ctf_stream_class
*stream_class
= NULL
;
3071 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3072 bool pop_scope
= false;
3074 if (node
->visited
) {
3078 node
->visited
= TRUE
;
3079 event_name
= get_event_decl_name(ctx
, node
);
3081 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `name` attribute in event class.");
3086 event_class
= ctf_event_class_create();
3087 BT_ASSERT(event_class
);
3088 g_string_assign(event_class
->name
, event_name
);
3089 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3092 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3093 ret
= visit_event_decl_entry(ctx
, iter
, event_class
, &stream_id
, &set
);
3095 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
3096 "Cannot visit event class's entry: "
3103 if (!_IS_SET(&set
, _EVENT_STREAM_ID_SET
)) {
3105 * Allow missing stream_id if there is only a single
3108 switch (ctx
->ctf_tc
->stream_classes
->len
) {
3110 /* Create implicit stream class if there's none */
3112 stream_class
= ctf_stream_class_create();
3113 BT_ASSERT(stream_class
);
3114 stream_class
->id
= stream_id
;
3115 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3118 /* Single stream class: get its ID */
3119 stream_class
= (ctf_stream_class
*) ctx
->ctf_tc
->stream_classes
->pdata
[0];
3120 stream_id
= stream_class
->id
;
3123 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `stream_id` attribute in event class.");
3129 /* We have the stream ID now; get the stream class if found */
3130 if (!stream_class
) {
3131 stream_class
= ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_id
);
3132 if (!stream_class
) {
3133 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3134 "Cannot find stream class at this point: "
3142 BT_ASSERT(stream_class
);
3144 if (!_IS_SET(&set
, _EVENT_ID_SET
)) {
3145 /* Allow only one event without ID per stream */
3146 if (stream_class
->event_classes
->len
!= 0) {
3147 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `id` attribute in event class.");
3153 event_class
->id
= 0;
3156 if (ctf_stream_class_borrow_event_class_by_id(stream_class
, event_class
->id
)) {
3157 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3158 "Duplicate event class (same ID) in the same stream class: "
3165 ctf_stream_class_append_event_class(stream_class
, event_class
);
3170 ctf_event_class_destroy(event_class
);
3187 static int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3188 struct ctf_field_class
*fc
)
3190 struct ctf_clock_class
*clock_class_to_map_to
= NULL
;
3191 uint64_t clock_class_count
;
3197 if (fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&& fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3201 ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
3203 if (int_fc
->mapped_clock_class
) {
3204 /* Already mapped */
3208 clock_class_count
= ctx
->ctf_tc
->clock_classes
->len
;
3210 switch (clock_class_count
) {
3213 * No clock class exists in the trace at this point. Create an
3214 * implicit one at 1 GHz, named `default`, and use this clock
3217 clock_class_to_map_to
= ctf_clock_class_create();
3218 BT_ASSERT(clock_class_to_map_to
);
3219 clock_class_to_map_to
->frequency
= UINT64_C(1000000000);
3220 g_string_assign(clock_class_to_map_to
->name
, "default");
3221 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock_class_to_map_to
);
3225 * Only one clock class exists in the trace at this point: use
3228 clock_class_to_map_to
= (ctf_clock_class
*) ctx
->ctf_tc
->clock_classes
->pdata
[0];
3232 * Timestamp field not mapped to a clock class and there's more
3233 * than one clock class in the trace: this is an error.
3235 BT_CPPLOGE_APPEND_CAUSE_SPEC(
3236 ctx
->logger
, "Timestamp field found with no mapped clock class, "
3237 "but there's more than one clock class in the trace at this point.");
3241 BT_ASSERT(clock_class_to_map_to
);
3242 int_fc
->mapped_clock_class
= clock_class_to_map_to
;
3247 static int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3248 struct ctf_field_class
*root_fc
,
3249 const char *field_name
)
3253 struct ctf_field_class_struct
*struct_fc
= (ctf_field_class_struct
*) root_fc
;
3254 struct ctf_field_class_variant
*var_fc
= (ctf_field_class_variant
*) root_fc
;
3260 if (root_fc
->type
!= CTF_FIELD_CLASS_TYPE_STRUCT
&&
3261 root_fc
->type
!= CTF_FIELD_CLASS_TYPE_VARIANT
) {
3265 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3266 count
= struct_fc
->members
->len
;
3268 count
= var_fc
->options
->len
;
3271 for (i
= 0; i
< count
; i
++) {
3272 struct ctf_named_field_class
*named_fc
= NULL
;
3274 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3275 named_fc
= ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
3276 } else if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
3277 named_fc
= ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
3282 if (strcmp(named_fc
->name
->str
, field_name
) == 0) {
3283 ret
= auto_map_field_to_trace_clock_class(ctx
, named_fc
->fc
);
3285 BT_CPPLOGE_APPEND_CAUSE_SPEC(
3287 "Cannot automatically map field to trace's clock class: "
3288 "field-name=\"{}\"",
3294 ret
= auto_map_fields_to_trace_clock_class(ctx
, named_fc
->fc
, field_name
);
3296 BT_CPPLOGE_APPEND_CAUSE_SPEC(
3298 "Cannot automatically map structure or variant field class's fields to trace's clock class: "
3299 "field-name=\"{}\", root-field-name=\"{}\"",
3300 field_name
, named_fc
->name
->str
);
3309 static int visit_stream_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3310 struct ctf_stream_class
*stream_class
, int *set
)
3315 switch (node
->type
) {
3317 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3318 &node
->u
.field_class_def
.field_class_declarators
);
3320 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in stream class.");
3324 case NODE_TYPEALIAS
:
3325 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3326 node
->u
.field_class_alias
.alias
);
3328 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3329 "Cannot add field class alias found in stream class.");
3333 case NODE_CTF_EXPRESSION
:
3335 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3337 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3342 if (strcmp(left
, "id") == 0) {
3345 if (_IS_SET(set
, _STREAM_ID_SET
)) {
3346 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "stream declaration");
3351 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
3353 /* Only read "id" if get_unary_unsigned() succeeded. */
3354 if (ret
|| (!ret
&& id
< 0)) {
3355 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3356 node
, "Unexpected unary expression for stream class's `id` attribute.");
3361 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, id
)) {
3362 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate stream class (same ID): id={}", id
);
3367 stream_class
->id
= id
;
3368 _SET(set
, _STREAM_ID_SET
);
3369 } else if (strcmp(left
, "event.header") == 0) {
3370 if (_IS_SET(set
, _STREAM_EVENT_HEADER_SET
)) {
3371 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3372 "Duplicate `event.header` entry in stream class.");
3377 ret
= visit_field_class_specifier_list(
3378 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3379 &stream_class
->event_header_fc
);
3381 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3382 node
, "Cannot create stream class's event header field class.");
3386 BT_ASSERT(stream_class
->event_header_fc
);
3387 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->event_header_fc
,
3390 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3392 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3396 _SET(set
, _STREAM_EVENT_HEADER_SET
);
3397 } else if (strcmp(left
, "event.context") == 0) {
3398 if (_IS_SET(set
, _STREAM_EVENT_CONTEXT_SET
)) {
3399 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3400 "Duplicate `event.context` entry in stream class.");
3405 ret
= visit_field_class_specifier_list(
3406 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3407 &stream_class
->event_common_context_fc
);
3409 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3410 node
, "Cannot create stream class's event context field class.");
3414 BT_ASSERT(stream_class
->event_common_context_fc
);
3415 _SET(set
, _STREAM_EVENT_CONTEXT_SET
);
3416 } else if (strcmp(left
, "packet.context") == 0) {
3417 if (_IS_SET(set
, _STREAM_PACKET_CONTEXT_SET
)) {
3418 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3419 "Duplicate `packet.context` entry in stream class.");
3424 ret
= visit_field_class_specifier_list(
3425 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3426 &stream_class
->packet_context_fc
);
3428 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3429 node
, "Cannot create stream class's packet context field class.");
3433 BT_ASSERT(stream_class
->packet_context_fc
);
3434 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3437 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3439 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3443 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3446 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3448 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3452 _SET(set
, _STREAM_PACKET_CONTEXT_SET
);
3454 _BT_CPPLOGW_NODE(node
,
3455 "Unknown attribute in stream class: "
3477 static int visit_stream_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3481 struct ctf_node
*iter
;
3482 struct ctf_stream_class
*stream_class
= NULL
;
3483 struct bt_list_head
*decl_list
= &node
->u
.stream
.declaration_list
;
3485 if (node
->visited
) {
3489 node
->visited
= TRUE
;
3490 stream_class
= ctf_stream_class_create();
3491 BT_ASSERT(stream_class
);
3492 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3494 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3495 ret
= visit_stream_decl_entry(ctx
, iter
, stream_class
, &set
);
3497 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
3498 "Cannot visit stream class's entry: "
3508 if (_IS_SET(&set
, _STREAM_ID_SET
)) {
3509 /* Check that packet header has `stream_id` field */
3510 struct ctf_named_field_class
*named_fc
= NULL
;
3512 if (!ctx
->ctf_tc
->packet_header_fc
) {
3513 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Stream class has a `id` attribute, "
3514 "but trace has no packet header field class.");
3519 named_fc
= ctf_field_class_struct_borrow_member_by_name(
3520 ctf_field_class_as_struct(ctx
->ctf_tc
->packet_header_fc
), "stream_id");
3522 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3523 node
, "Stream class has a `id` attribute, "
3524 "but trace's packet header field class has no `stream_id` field.");
3529 if (named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3530 named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3531 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3533 "Stream class has a `id` attribute, "
3534 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3539 /* Allow only _one_ ID-less stream */
3540 if (ctx
->ctf_tc
->stream_classes
->len
!= 0) {
3541 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3543 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3548 /* Automatic ID: 0 */
3549 stream_class
->id
= 0;
3553 * Make sure that this stream class's ID is currently unique in
3556 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_class
->id
)) {
3557 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate stream class (same ID): id={}",
3563 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3564 stream_class
= NULL
;
3568 ctf_stream_class_destroy(stream_class
);
3569 stream_class
= NULL
;
3575 static int visit_trace_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3582 switch (node
->type
) {
3584 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3585 &node
->u
.field_class_def
.field_class_declarators
);
3587 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3588 "Cannot add field class found in trace (`trace` block).");
3592 case NODE_TYPEALIAS
:
3593 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3594 node
->u
.field_class_alias
.alias
);
3596 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3597 node
, "Cannot add field class alias found in trace (`trace` block).");
3601 case NODE_CTF_EXPRESSION
:
3603 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3605 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3610 if (strcmp(left
, "major") == 0) {
3611 if (_IS_SET(set
, _TRACE_MAJOR_SET
)) {
3612 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "major", "trace");
3617 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3619 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3620 node
, "Unexpected unary expression for trace's `major` attribute.");
3626 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3627 "Invalid trace's `minor` attribute: expecting 1.");
3632 ctx
->ctf_tc
->major
= val
;
3633 _SET(set
, _TRACE_MAJOR_SET
);
3634 } else if (strcmp(left
, "minor") == 0) {
3635 if (_IS_SET(set
, _TRACE_MINOR_SET
)) {
3636 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "minor", "trace");
3641 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3643 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3644 node
, "Unexpected unary expression for trace's `minor` attribute.");
3650 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3651 "Invalid trace's `minor` attribute: expecting 8.");
3656 ctx
->ctf_tc
->minor
= val
;
3657 _SET(set
, _TRACE_MINOR_SET
);
3658 } else if (strcmp(left
, "uuid") == 0) {
3659 if (_IS_SET(set
, _TRACE_UUID_SET
)) {
3660 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "uuid", "trace");
3665 ret
= get_unary_uuid(&node
->u
.ctf_expression
.right
, ctx
->ctf_tc
->uuid
, ctx
->logger
);
3667 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Invalid trace's `uuid` attribute.");
3671 ctx
->ctf_tc
->is_uuid_set
= true;
3672 _SET(set
, _TRACE_UUID_SET
);
3673 } else if (strcmp(left
, "byte_order") == 0) {
3674 /* Default byte order is already known at this stage */
3675 if (_IS_SET(set
, _TRACE_BYTE_ORDER_SET
)) {
3676 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
3681 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
!= CTF_BYTE_ORDER_UNKNOWN
);
3682 _SET(set
, _TRACE_BYTE_ORDER_SET
);
3683 } else if (strcmp(left
, "packet.header") == 0) {
3684 if (_IS_SET(set
, _TRACE_PACKET_HEADER_SET
)) {
3685 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate `packet.header` entry in trace.");
3690 ret
= visit_field_class_specifier_list(
3691 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3692 &ctx
->ctf_tc
->packet_header_fc
);
3694 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3695 "Cannot create trace's packet header field class.");
3699 BT_ASSERT(ctx
->ctf_tc
->packet_header_fc
);
3700 _SET(set
, _TRACE_PACKET_HEADER_SET
);
3702 _BT_CPPLOGW_NODE(node
,
3703 "Unknown attribute in stream class: "
3713 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Unknown expression in trace.");
3725 static int visit_trace_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3729 struct ctf_node
*iter
;
3730 struct bt_list_head
*decl_list
= &node
->u
.trace
.declaration_list
;
3732 if (node
->visited
) {
3736 node
->visited
= TRUE
;
3738 if (ctx
->is_trace_visited
) {
3739 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
3744 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3746 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3747 ret
= visit_trace_decl_entry(ctx
, iter
, &set
);
3749 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
3750 "Cannot visit trace's entry (`trace` block): "
3760 if (!_IS_SET(&set
, _TRACE_MAJOR_SET
)) {
3761 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `major` attribute in trace (`trace` block).");
3766 if (!_IS_SET(&set
, _TRACE_MINOR_SET
)) {
3767 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Missing `minor` attribute in trace (`trace` block).");
3772 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3773 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
3774 "Missing `byte_order` attribute in trace (`trace` block).");
3779 ctx
->is_trace_visited
= true;
3788 static int visit_env(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3792 struct ctf_node
*entry_node
;
3793 struct bt_list_head
*decl_list
= &node
->u
.env
.declaration_list
;
3795 if (node
->visited
) {
3799 node
->visited
= TRUE
;
3801 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
3802 struct bt_list_head
*right_head
= &entry_node
->u
.ctf_expression
.right
;
3804 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
3805 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
,
3806 "Wrong expression in environment entry: "
3813 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
3815 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot get environment entry's name.");
3820 if (is_unary_string(right_head
)) {
3821 char *right
= ctf_ast_concatenate_unary_strings(right_head
);
3824 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3826 "Unexpected unary expression for environment entry's value: "
3833 if (strcmp(left
, "tracer_name") == 0) {
3834 if (strncmp(right
, "lttng", 5) == 0) {
3835 BT_CPPLOGI_SPEC(ctx
->logger
,
3836 "Detected LTTng trace from `{}` environment value: "
3837 "tracer-name=\"{}\"",
3839 ctx
->is_lttng
= true;
3843 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
,
3846 } else if (is_unary_unsigned(right_head
) || is_unary_signed(right_head
)) {
3849 if (is_unary_unsigned(right_head
)) {
3850 ret
= get_unary_unsigned(ctx
, right_head
, (uint64_t *) &v
);
3852 ret
= get_unary_signed(right_head
, &v
);
3855 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3857 "Unexpected unary expression for environment entry's value: "
3864 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
,
3867 _BT_CPPLOGW_NODE(entry_node
,
3868 "Environment entry has unknown type: "
3885 static int set_trace_byte_order(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*trace_node
)
3890 struct ctf_node
*node
;
3891 struct bt_list_head
*decl_list
= &trace_node
->u
.trace
.declaration_list
;
3893 bt_list_for_each_entry (node
, decl_list
, siblings
) {
3894 if (node
->type
== NODE_CTF_EXPRESSION
) {
3895 struct ctf_node
*right_node
;
3897 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3899 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3904 if (strcmp(left
, "byte_order") == 0) {
3905 enum ctf_byte_order bo
;
3907 if (_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3908 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
3913 _SET(&set
, _TRACE_BYTE_ORDER_SET
);
3915 _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
3916 bo
= byte_order_from_unary_expr(ctx
, right_node
);
3917 if (bo
== CTF_BYTE_ORDER_UNKNOWN
) {
3918 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3919 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
3920 "expecting `le`, `be`, or `network`.");
3923 } else if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
3924 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3925 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
3926 "cannot be set to `native` here.");
3931 ctx
->ctf_tc
->default_byte_order
= bo
;
3939 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3940 _BT_CPPLOGE_APPEND_CAUSE_NODE(trace_node
,
3941 "Missing `byte_order` attribute in trace (`trace` block).");
3953 static int visit_clock_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
3954 struct ctf_clock_class
*clock
, int *set
, int64_t *offset_seconds
,
3955 uint64_t *offset_cycles
)
3960 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
3961 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type={}",
3967 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
3969 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot concatenate unary strings.");
3974 if (strcmp(left
, "name") == 0) {
3977 if (_IS_SET(set
, _CLOCK_NAME_SET
)) {
3978 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "name", "clock class");
3983 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
3985 _BT_CPPLOGE_APPEND_CAUSE_NODE(
3986 entry_node
, "Unexpected unary expression for clock class's `name` attribute.");
3991 g_string_assign(clock
->name
, right
);
3993 _SET(set
, _CLOCK_NAME_SET
);
3994 } else if (strcmp(left
, "uuid") == 0) {
3997 if (_IS_SET(set
, _CLOCK_UUID_SET
)) {
3998 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "uuid", "clock class");
4003 ret
= get_unary_uuid(&entry_node
->u
.ctf_expression
.right
, uuid
, ctx
->logger
);
4005 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Invalid clock class's `uuid` attribute.");
4009 clock
->has_uuid
= true;
4010 bt_uuid_copy(clock
->uuid
, uuid
);
4011 _SET(set
, _CLOCK_UUID_SET
);
4012 } else if (strcmp(left
, "description") == 0) {
4015 if (_IS_SET(set
, _CLOCK_DESCRIPTION_SET
)) {
4016 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "description", "clock class");
4021 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4023 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4025 "Unexpected unary expression for clock class's `description` attribute.");
4030 g_string_assign(clock
->description
, right
);
4032 _SET(set
, _CLOCK_DESCRIPTION_SET
);
4033 } else if (strcmp(left
, "freq") == 0) {
4034 uint64_t freq
= UINT64_C(-1);
4036 if (_IS_SET(set
, _CLOCK_FREQ_SET
)) {
4037 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "freq", "clock class");
4042 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &freq
);
4044 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4045 entry_node
, "Unexpected unary expression for clock class's `freq` attribute.");
4050 if (freq
== UINT64_C(-1) || freq
== 0) {
4051 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Invalid clock class frequency: freq={}",
4057 clock
->frequency
= freq
;
4058 _SET(set
, _CLOCK_FREQ_SET
);
4059 } else if (strcmp(left
, "precision") == 0) {
4062 if (_IS_SET(set
, _CLOCK_PRECISION_SET
)) {
4063 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "precision", "clock class");
4068 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &precision
);
4070 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4071 entry_node
, "Unexpected unary expression for clock class's `precision` attribute.");
4076 clock
->precision
= precision
;
4077 _SET(set
, _CLOCK_PRECISION_SET
);
4078 } else if (strcmp(left
, "offset_s") == 0) {
4079 if (_IS_SET(set
, _CLOCK_OFFSET_S_SET
)) {
4080 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset_s", "clock class");
4085 ret
= get_unary_signed(&entry_node
->u
.ctf_expression
.right
, offset_seconds
);
4087 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4088 entry_node
, "Unexpected unary expression for clock class's `offset_s` attribute.");
4093 _SET(set
, _CLOCK_OFFSET_S_SET
);
4094 } else if (strcmp(left
, "offset") == 0) {
4095 if (_IS_SET(set
, _CLOCK_OFFSET_SET
)) {
4096 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset", "clock class");
4101 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, offset_cycles
);
4103 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4104 entry_node
, "Unexpected unary expression for clock class's `offset` attribute.");
4109 _SET(set
, _CLOCK_OFFSET_SET
);
4110 } else if (strcmp(left
, "absolute") == 0) {
4111 struct ctf_node
*right
;
4113 if (_IS_SET(set
, _CLOCK_ABSOLUTE_SET
)) {
4114 _BT_CPPLOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "absolute", "clock class");
4120 _BT_LIST_FIRST_ENTRY(&entry_node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4121 ret
= get_boolean(ctx
, right
);
4123 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4124 entry_node
, "Unexpected unary expression for clock class's `absolute` attribute.");
4129 clock
->is_absolute
= ret
;
4130 _SET(set
, _CLOCK_ABSOLUTE_SET
);
4132 _BT_CPPLOGW_NODE(entry_node
, "Unknown attribute in clock class: attr-name=\"{}\"", left
);
4144 static int visit_clock_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*clock_node
)
4148 struct ctf_clock_class
*clock
;
4149 struct ctf_node
*entry_node
;
4150 struct bt_list_head
*decl_list
= &clock_node
->u
.clock
.declaration_list
;
4151 const char *clock_class_name
;
4152 int64_t offset_seconds
= 0;
4153 uint64_t offset_cycles
= 0;
4154 long long offsetSecLL
;
4155 unsigned long long offsetCyclesULL
;
4157 if (clock_node
->visited
) {
4161 clock_node
->visited
= TRUE
;
4163 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4164 clock
= ctf_clock_class_create();
4166 _BT_CPPLOGE_APPEND_CAUSE_NODE(clock_node
, "Cannot create default clock class.");
4171 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
4172 ret
= visit_clock_decl_entry(ctx
, entry_node
, clock
, &set
, &offset_seconds
, &offset_cycles
);
4174 _BT_CPPLOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot visit clock class's entry: ret={}",
4180 if (!_IS_SET(&set
, _CLOCK_NAME_SET
)) {
4181 _BT_CPPLOGE_APPEND_CAUSE_NODE(clock_node
, "Missing `name` attribute in clock class.");
4186 clock_class_name
= clock
->name
->str
;
4187 BT_ASSERT(clock_class_name
);
4188 if (ctx
->is_lttng
&& strcmp(clock_class_name
, "monotonic") == 0) {
4190 * Old versions of LTTng forgot to set its clock class
4191 * as absolute, even if it is. This is important because
4192 * it's a condition to be able to sort messages
4193 * from different sources.
4195 clock
->is_absolute
= true;
4199 * Adjust offsets so that the part in cycles is less than the
4200 * frequency (move to the part in seconds).
4203 offsetSecLL
= offset_seconds
;
4204 offsetCyclesULL
= offset_cycles
;
4205 const auto normalized
=
4206 ctf::src::normalizeClkOffset(offsetSecLL
, offsetCyclesULL
, clock
->frequency
);
4207 offsetSecLL
= normalized
.first
;
4208 offsetCyclesULL
= normalized
.second
;
4209 BT_ASSERT(offsetCyclesULL
< clock
->frequency
);
4210 clock
->offset_seconds
= offsetSecLL
;
4211 clock
->offset_cycles
= offsetCyclesULL
;
4214 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock
);
4219 ctf_clock_class_destroy(clock
);
4225 static int visit_root_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*root_decl_node
)
4229 if (root_decl_node
->visited
) {
4233 root_decl_node
->visited
= TRUE
;
4235 switch (root_decl_node
->type
) {
4238 visit_field_class_def(ctx
, root_decl_node
->u
.field_class_def
.field_class_specifier_list
,
4239 &root_decl_node
->u
.field_class_def
.field_class_declarators
);
4241 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node
,
4242 "Cannot add field class found in root scope.");
4246 case NODE_TYPEALIAS
:
4247 ret
= visit_field_class_alias(ctx
, root_decl_node
->u
.field_class_alias
.target
,
4248 root_decl_node
->u
.field_class_alias
.alias
);
4250 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node
,
4251 "Cannot add field class alias found in root scope.");
4255 case NODE_TYPE_SPECIFIER_LIST
:
4257 struct ctf_field_class
*decl
= NULL
;
4260 * Just add the field class specifier to the root
4261 * declaration scope. Put local reference.
4263 ret
= visit_field_class_specifier_list(ctx
, root_decl_node
, &decl
);
4265 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node
,
4266 "Cannot visit root scope's field class: "
4273 ctf_field_class_destroy(decl
);
4278 _BT_CPPLOGE_APPEND_CAUSE_NODE(root_decl_node
, "Unexpected node type: node-type={}",
4279 root_decl_node
->type
);
4288 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
4292 BT_CPPLOGI_SPEC(ctx
->logger
, "Visiting metadata's AST to generate CTF IR objects.");
4294 switch (node
->type
) {
4297 struct ctf_node
*iter
;
4298 bool got_trace_decl
= false;
4301 * The first thing we need is the native byte order of
4302 * the trace block, because early class aliases can have
4303 * a `byte_order` attribute set to `native`. If we don't
4304 * have the native byte order yet, and we don't have any
4305 * trace block yet, then fail with EINCOMPLETE.
4307 if (ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
4308 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4309 if (got_trace_decl
) {
4310 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
4315 ret
= set_trace_byte_order(ctx
, iter
);
4317 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
,
4318 "Cannot set trace's native byte order: "
4324 got_trace_decl
= true;
4327 if (!got_trace_decl
) {
4328 BT_CPPLOGD_SPEC(ctx
->logger
, "Incomplete AST: need trace (`trace` block).");
4334 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_LITTLE
||
4335 ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_BIG
);
4336 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4339 bt_list_for_each_entry (iter
, &node
->u
.root
.env
, siblings
) {
4340 ret
= visit_env(ctx
, iter
);
4342 _BT_CPPLOGE_APPEND_CAUSE_NODE(
4344 "Cannot visit trace's environment (`env` block) entry: "
4351 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4354 * Visit clock blocks.
4356 bt_list_for_each_entry (iter
, &node
->u
.root
.clock
, siblings
) {
4357 ret
= visit_clock_decl(ctx
, iter
);
4359 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit clock class: ret={}", ret
);
4364 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4367 * Visit root declarations next, as they can be used by any
4370 bt_list_for_each_entry (iter
, &node
->u
.root
.declaration_list
, siblings
) {
4371 ret
= visit_root_decl(ctx
, iter
);
4373 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit root entry: ret={}", ret
);
4378 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4380 /* Callsite blocks are not supported */
4381 bt_list_for_each_entry (iter
, &node
->u
.root
.callsite
, siblings
) {
4382 _BT_CPPLOGW_NODE(iter
, "\"callsite\" blocks are not supported as of this version.");
4385 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4388 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4389 ret
= visit_trace_decl(ctx
, iter
);
4391 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
,
4392 "Cannot visit trace (`trace` block): "
4399 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4402 bt_list_for_each_entry (iter
, &node
->u
.root
.stream
, siblings
) {
4403 ret
= visit_stream_decl(ctx
, iter
);
4405 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit stream class: ret={}", ret
);
4410 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4413 bt_list_for_each_entry (iter
, &node
->u
.root
.event
, siblings
) {
4414 ret
= visit_event_decl(ctx
, iter
);
4416 _BT_CPPLOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit event class: ret={}", ret
);
4421 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4425 _BT_CPPLOGE_APPEND_CAUSE_NODE(node
, "Unexpected node type: node-type={}", node
->type
);
4430 /* Update default clock classes */
4431 ret
= ctf_trace_class_update_default_clock_classes(ctx
->ctf_tc
, ctx
->logger
);
4437 /* Update trace class meanings */
4438 ret
= ctf_trace_class_update_meanings(ctx
->ctf_tc
);
4444 /* Update text arrays and sequences */
4445 ret
= ctf_trace_class_update_text_array_sequence(ctx
->ctf_tc
);
4451 /* Update structure/array/sequence alignments */
4452 ret
= ctf_trace_class_update_alignments(ctx
->ctf_tc
);
4458 /* Resolve sequence lengths and variant tags */
4459 ret
= ctf_trace_class_resolve_field_classes(ctx
->ctf_tc
, ctx
->logger
);
4465 /* Validate what we have so far */
4466 ret
= ctf_trace_class_validate(ctx
->ctf_tc
, ctx
->logger
);
4473 * If there are fields which are not related to the CTF format
4474 * itself in the packet header and in event header field
4475 * classes, warn about it because they are never translated.
4477 ctf_trace_class_warn_meaningless_header_fields(ctx
->ctf_tc
, ctx
->logger
);