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).
10 #define BT_COMP_LOG_SELF_COMP (ctx->log_cfg.self_comp)
11 #define BT_COMP_LOG_SELF_COMP_CLASS (ctx->log_cfg.self_comp_class)
12 #define BT_LOG_OUTPUT_LEVEL (ctx->log_cfg.log_level)
13 #define BT_LOG_TAG "PLUGIN/CTF/META/IR-VISITOR"
14 #include "logging/comp-logging.h"
22 #include "common/assert.h"
27 #include "common/common.h"
28 #include "common/uuid.h"
29 #include "compat/endian.h"
30 #include <babeltrace2/babeltrace.h>
32 #include "logging.hpp"
33 #include "scanner.hpp"
35 #include "decoder.hpp"
36 #include "ctf-meta.hpp"
37 #include "ctf-meta-visitors.hpp"
39 /* Bit value (left shift) */
40 #define _BV(_val) (1 << (_val))
42 /* Bit is set in a set of bits */
43 #define _IS_SET(_set, _mask) (*(_set) & (_mask))
45 /* Set bit in a set of bits */
46 #define _SET(_set, _mask) (*(_set) |= (_mask))
48 /* Try to push scope, or go to the `error` label */
49 #define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
51 ret = ctx_push_scope(ctx); \
53 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot push scope."); \
58 /* Bits for verifying existing attributes in various declarations */
61 _CLOCK_NAME_SET
= _BV(0),
62 _CLOCK_UUID_SET
= _BV(1),
63 _CLOCK_FREQ_SET
= _BV(2),
64 _CLOCK_PRECISION_SET
= _BV(3),
65 _CLOCK_OFFSET_S_SET
= _BV(4),
66 _CLOCK_OFFSET_SET
= _BV(5),
67 _CLOCK_ABSOLUTE_SET
= _BV(6),
68 _CLOCK_DESCRIPTION_SET
= _BV(7),
73 _INTEGER_ALIGN_SET
= _BV(0),
74 _INTEGER_SIZE_SET
= _BV(1),
75 _INTEGER_BASE_SET
= _BV(2),
76 _INTEGER_ENCODING_SET
= _BV(3),
77 _INTEGER_BYTE_ORDER_SET
= _BV(4),
78 _INTEGER_SIGNED_SET
= _BV(5),
79 _INTEGER_MAP_SET
= _BV(6),
84 _FLOAT_ALIGN_SET
= _BV(0),
85 _FLOAT_MANT_DIG_SET
= _BV(1),
86 _FLOAT_EXP_DIG_SET
= _BV(2),
87 _FLOAT_BYTE_ORDER_SET
= _BV(3),
92 _STRING_ENCODING_SET
= _BV(0),
97 _TRACE_MINOR_SET
= _BV(0),
98 _TRACE_MAJOR_SET
= _BV(1),
99 _TRACE_BYTE_ORDER_SET
= _BV(2),
100 _TRACE_UUID_SET
= _BV(3),
101 _TRACE_PACKET_HEADER_SET
= _BV(4),
106 _STREAM_ID_SET
= _BV(0),
107 _STREAM_PACKET_CONTEXT_SET
= _BV(1),
108 _STREAM_EVENT_HEADER_SET
= _BV(2),
109 _STREAM_EVENT_CONTEXT_SET
= _BV(3),
114 _EVENT_NAME_SET
= _BV(0),
115 _EVENT_ID_SET
= _BV(1),
116 _EVENT_MODEL_EMF_URI_SET
= _BV(2),
117 _EVENT_STREAM_ID_SET
= _BV(3),
118 _EVENT_LOG_LEVEL_SET
= _BV(4),
119 _EVENT_CONTEXT_SET
= _BV(5),
120 _EVENT_FIELDS_SET
= _BV(6),
129 LOG_LEVEL_WARNING
= 4,
130 LOG_LEVEL_NOTICE
= 5,
132 LOG_LEVEL_DEBUG_SYSTEM
= 7,
133 LOG_LEVEL_DEBUG_PROGRAM
= 8,
134 LOG_LEVEL_DEBUG_PROCESS
= 9,
135 LOG_LEVEL_DEBUG_MODULE
= 10,
136 LOG_LEVEL_DEBUG_UNIT
= 11,
137 LOG_LEVEL_DEBUG_FUNCTION
= 12,
138 LOG_LEVEL_DEBUG_LINE
= 13,
139 LOG_LEVEL_DEBUG
= 14,
143 /* Prefixes of class aliases */
144 #define _PREFIX_ALIAS 'a'
145 #define _PREFIX_ENUM 'e'
146 #define _PREFIX_STRUCT 's'
147 #define _PREFIX_VARIANT 'v'
149 /* First entry in a BT list */
150 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) bt_list_entry((_ptr)->next, _class, _member)
152 #define _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \
153 _BT_COMP_LOGE_APPEND_CAUSE_LINENO( \
154 (_node)->lineno, "Duplicate attribute in %s: attr-name=\"%s\"", _entity, _attr)
156 #define _BT_COMP_LOGE_NODE(_node, _msg, args...) _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ##args)
158 #define _BT_COMP_LOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
159 _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, _msg, ##args)
161 #define _BT_COMP_LOGW_NODE(_node, _msg, args...) _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ##args)
163 #define _BT_COMP_LOGT_NODE(_node, _msg, args...) _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ##args)
166 * Declaration scope of a visitor context. This represents a TSDL
167 * lexical scope, so that aliases and named structures, variants,
168 * and enumerations may be registered and looked up hierarchically.
170 struct ctx_decl_scope
173 * Alias name to field class.
175 * GQuark -> struct ctf_field_class * (owned by this)
177 GHashTable
*decl_map
;
179 /* Parent scope; NULL if this is the root declaration scope */
180 struct ctx_decl_scope
*parent_scope
;
184 * Visitor context (private).
186 struct ctf_visitor_generate_ir
188 struct meta_log_config log_cfg
;
190 /* Trace IR trace class being filled (owned by this) */
191 bt_trace_class
*trace_class
;
193 /* CTF meta trace being filled (owned by this) */
194 struct ctf_trace_class
*ctf_tc
;
196 /* Current declaration scope (top of the stack) (owned by this) */
197 struct ctx_decl_scope
*current_scope
;
199 /* True if trace declaration is visited */
200 bool is_trace_visited
;
202 /* True if this is an LTTng trace */
205 /* Config passed by the user */
206 struct ctf_metadata_decoder_config decoder_config
;
212 struct ctf_visitor_generate_ir
;
215 * Creates a new declaration scope.
217 * @param par_scope Parent scope (NULL if creating a root scope)
218 * @returns New declaration scope, or NULL on error
220 static struct ctx_decl_scope
*ctx_decl_scope_create(struct ctf_visitor_generate_ir
*ctx
,
221 struct ctx_decl_scope
*par_scope
)
223 struct ctx_decl_scope
*scope
;
225 scope
= g_new(struct ctx_decl_scope
, 1);
227 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate one declaration scope.");
231 scope
->decl_map
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
,
232 (GDestroyNotify
) ctf_field_class_destroy
);
233 scope
->parent_scope
= par_scope
;
240 * Destroys a declaration scope.
242 * This function does not destroy the parent scope.
244 * @param scope Scope to destroy
246 static void ctx_decl_scope_destroy(struct ctx_decl_scope
*scope
)
252 g_hash_table_destroy(scope
->decl_map
);
260 * Returns the GQuark of a prefixed alias.
262 * @param prefix Prefix character
264 * @returns Associated GQuark, or 0 on error
266 static GQuark
get_prefixed_named_quark(struct ctf_visitor_generate_ir
*ctx
, char prefix
,
270 std::string prname
= std::string
{prefix
} + name
;
271 return g_quark_from_string(prname
.c_str());
275 * Looks up a prefixed class alias within a declaration scope.
277 * @param scope Declaration scope
278 * @param prefix Prefix character
279 * @param name Alias name
280 * @param levels Number of levels to dig into (-1 means infinite)
281 * @param copy True to return a copy
282 * @returns Declaration (owned by caller if \p copy is true),
283 * or NULL if not found
285 static struct ctf_field_class
*
286 ctx_decl_scope_lookup_prefix_alias(struct ctf_visitor_generate_ir
*ctx
,
287 struct ctx_decl_scope
*scope
, char prefix
, const char *name
,
288 int levels
, bool copy
)
292 struct ctf_field_class
*decl
= NULL
;
293 struct ctx_decl_scope
*cur_scope
= scope
;
297 qname
= get_prefixed_named_quark(ctx
, prefix
, name
);
306 while (cur_scope
&& cur_levels
< levels
) {
307 decl
= (ctf_field_class
*) g_hash_table_lookup(cur_scope
->decl_map
,
308 (gconstpointer
) GUINT_TO_POINTER(qname
));
310 /* Caller's reference */
312 decl
= ctf_field_class_copy(decl
);
319 cur_scope
= cur_scope
->parent_scope
;
328 * Looks up a class alias within a declaration scope.
330 * @param scope Declaration scope
331 * @param name Alias name
332 * @param levels Number of levels to dig into (-1 means infinite)
333 * @param copy True to return a copy
334 * @returns Declaration (owned by caller if \p copy is true),
335 * or NULL if not found
337 static struct ctf_field_class
*ctx_decl_scope_lookup_alias(struct ctf_visitor_generate_ir
*ctx
,
338 struct ctx_decl_scope
*scope
,
339 const char *name
, int levels
, bool copy
)
341 return ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, _PREFIX_ALIAS
, name
, levels
, copy
);
345 * Looks up an enumeration within a declaration scope.
347 * @param scope Declaration scope
348 * @param name Enumeration name
349 * @param levels Number of levels to dig into (-1 means infinite)
350 * @param copy True to return a copy
351 * @returns Declaration (owned by caller if \p copy is true),
352 * or NULL if not found
354 static struct ctf_field_class_enum
*ctx_decl_scope_lookup_enum(struct ctf_visitor_generate_ir
*ctx
,
355 struct ctx_decl_scope
*scope
,
356 const char *name
, int levels
,
359 return ctf_field_class_as_enum(
360 ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, _PREFIX_ENUM
, name
, levels
, copy
));
364 * Looks up a structure within a declaration scope.
366 * @param scope Declaration scope
367 * @param name Structure name
368 * @param levels Number of levels to dig into (-1 means infinite)
369 * @param copy True to return a copy
370 * @returns Declaration (owned by caller if \p copy is true),
371 * or NULL if not found
373 static struct ctf_field_class_struct
*
374 ctx_decl_scope_lookup_struct(struct ctf_visitor_generate_ir
*ctx
, struct ctx_decl_scope
*scope
,
375 const char *name
, int levels
, bool copy
)
377 return ctf_field_class_as_struct(
378 ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, _PREFIX_STRUCT
, name
, levels
, copy
));
382 * Looks up a variant within a declaration scope.
384 * @param scope Declaration scope
385 * @param name Variant name
386 * @param levels Number of levels to dig into (-1 means infinite)
387 * @param copy True to return a copy
388 * @returns Declaration (owned by caller if \p copy is true),
389 * or NULL if not found
391 static struct ctf_field_class_variant
*
392 ctx_decl_scope_lookup_variant(struct ctf_visitor_generate_ir
*ctx
, struct ctx_decl_scope
*scope
,
393 const char *name
, int levels
, bool copy
)
395 return ctf_field_class_as_variant(
396 ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, _PREFIX_VARIANT
, name
, levels
, copy
));
400 * Registers a prefixed class alias within a declaration scope.
402 * @param scope Declaration scope
403 * @param prefix Prefix character
404 * @param name Alias name (non-NULL)
405 * @param decl Field class to register (copied)
406 * @returns 0 if registration went okay, negative value otherwise
408 static int ctx_decl_scope_register_prefix_alias(struct ctf_visitor_generate_ir
*ctx
,
409 struct ctx_decl_scope
*scope
, char prefix
,
410 const char *name
, struct ctf_field_class
*decl
)
418 qname
= get_prefixed_named_quark(ctx
, prefix
, name
);
424 /* Make sure alias does not exist in local scope */
425 if (ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, prefix
, name
, 1, false)) {
430 decl
= ctf_field_class_copy(decl
);
432 g_hash_table_insert(scope
->decl_map
, GUINT_TO_POINTER(qname
), decl
);
439 * Registers a class alias within a declaration scope.
441 * @param scope Declaration scope
442 * @param name Alias name (non-NULL)
443 * @param decl Field class to register (copied)
444 * @returns 0 if registration went okay, negative value otherwise
446 static int ctx_decl_scope_register_alias(struct ctf_visitor_generate_ir
*ctx
,
447 struct ctx_decl_scope
*scope
, const char *name
,
448 struct ctf_field_class
*decl
)
450 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_ALIAS
, name
, decl
);
454 * Registers an enumeration declaration within a declaration scope.
456 * @param scope Declaration scope
457 * @param name Enumeration name (non-NULL)
458 * @param decl Enumeration field class to register (copied)
459 * @returns 0 if registration went okay, negative value otherwise
461 static int ctx_decl_scope_register_enum(struct ctf_visitor_generate_ir
*ctx
,
462 struct ctx_decl_scope
*scope
, const char *name
,
463 struct ctf_field_class_enum
*decl
)
465 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_ENUM
, name
,
466 &decl
->base
.base
.base
);
470 * Registers a structure declaration within a declaration scope.
472 * @param scope Declaration scope
473 * @param name Structure name (non-NULL)
474 * @param decl Structure field class to register (copied)
475 * @returns 0 if registration went okay, negative value otherwise
477 static int ctx_decl_scope_register_struct(struct ctf_visitor_generate_ir
*ctx
,
478 struct ctx_decl_scope
*scope
, const char *name
,
479 struct ctf_field_class_struct
*decl
)
481 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_STRUCT
, name
, &decl
->base
);
485 * Registers a variant declaration within a declaration scope.
487 * @param scope Declaration scope
488 * @param name Variant name (non-NULL)
489 * @param decl Variant field class to register
490 * @returns 0 if registration went okay, negative value otherwise
492 static int ctx_decl_scope_register_variant(struct ctf_visitor_generate_ir
*ctx
,
493 struct ctx_decl_scope
*scope
, const char *name
,
494 struct ctf_field_class_variant
*decl
)
496 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_VARIANT
, name
, &decl
->base
);
500 * Destroys a visitor context.
502 * @param ctx Visitor context to destroy
504 static void ctx_destroy(struct ctf_visitor_generate_ir
*ctx
)
506 struct ctx_decl_scope
*scope
;
512 scope
= ctx
->current_scope
;
515 * Destroy all scopes, from current one to the root scope.
518 struct ctx_decl_scope
*parent_scope
= scope
->parent_scope
;
520 ctx_decl_scope_destroy(scope
);
521 scope
= parent_scope
;
524 bt_trace_class_put_ref(ctx
->trace_class
);
527 ctf_trace_class_destroy(ctx
->ctf_tc
);
537 * Creates a new visitor context.
539 * @param trace Associated trace
540 * @returns New visitor context, or NULL on error
542 static struct ctf_visitor_generate_ir
*
543 ctx_create(const struct ctf_metadata_decoder_config
*decoder_config
)
545 struct ctf_visitor_generate_ir
*ctx
= NULL
;
547 BT_ASSERT(decoder_config
);
549 ctx
= g_new0(struct ctf_visitor_generate_ir
, 1);
551 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
, decoder_config
->self_comp
,
552 "Failed to allocate one visitor context.");
556 ctx
->log_cfg
.log_level
= decoder_config
->log_level
;
557 ctx
->log_cfg
.self_comp
= decoder_config
->self_comp
;
558 ctx
->log_cfg
.self_comp_class
= decoder_config
->self_comp_class
;
560 if (decoder_config
->self_comp
) {
561 ctx
->trace_class
= bt_trace_class_create(decoder_config
->self_comp
);
562 if (!ctx
->trace_class
) {
563 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create empty trace class.");
568 ctx
->ctf_tc
= ctf_trace_class_create();
570 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create CTF trace class.");
574 /* Root declaration scope */
575 ctx
->current_scope
= ctx_decl_scope_create(ctx
, NULL
);
576 if (!ctx
->current_scope
) {
577 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
581 ctx
->decoder_config
= *decoder_config
;
593 * Pushes a new declaration scope on top of a visitor context's
594 * declaration scope stack.
596 * @param ctx Visitor context
597 * @returns 0 on success, or a negative value on error
599 static int ctx_push_scope(struct ctf_visitor_generate_ir
*ctx
)
602 struct ctx_decl_scope
*new_scope
;
605 new_scope
= ctx_decl_scope_create(ctx
, ctx
->current_scope
);
607 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
612 ctx
->current_scope
= new_scope
;
618 static void ctx_pop_scope(struct ctf_visitor_generate_ir
*ctx
)
620 struct ctx_decl_scope
*parent_scope
= NULL
;
624 if (!ctx
->current_scope
) {
628 parent_scope
= ctx
->current_scope
->parent_scope
;
629 ctx_decl_scope_destroy(ctx
->current_scope
);
630 ctx
->current_scope
= parent_scope
;
636 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
637 struct ctf_node
*ts_list
,
638 struct ctf_field_class
**decl
);
640 static int is_unary_string(struct bt_list_head
*head
)
643 struct ctf_node
*node
;
645 bt_list_for_each_entry (node
, head
, siblings
) {
646 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
650 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
658 static const char *get_map_clock_name_value(struct bt_list_head
*head
)
661 struct ctf_node
*node
;
662 const char *name
= NULL
;
664 bt_list_for_each_entry (node
, head
, siblings
) {
666 int uexpr_type
= node
->u
.unary_expression
.type
;
667 int uexpr_link
= node
->u
.unary_expression
.link
;
668 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_STRING
||
669 !((uexpr_link
!= UNARY_LINK_UNKNOWN
) ^ (i
== 0));
674 /* Needs to be chained with . */
675 switch (node
->u
.unary_expression
.link
) {
678 case UNARY_ARROWLINK
:
679 case UNARY_DOTDOTDOT
:
685 src_string
= node
->u
.unary_expression
.u
.string
;
689 if (strcmp("clock", src_string
)) {
697 if (strcmp("value", src_string
)) {
702 /* Extra identifier, unknown */
715 static int is_unary_unsigned(struct bt_list_head
*head
)
718 struct ctf_node
*node
;
720 bt_list_for_each_entry (node
, head
, siblings
) {
721 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
725 if (node
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
733 static int get_unary_unsigned(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
738 struct ctf_node
*node
;
742 if (bt_list_empty(head
)) {
747 bt_list_for_each_entry (node
, head
, siblings
) {
748 int uexpr_type
= node
->u
.unary_expression
.type
;
749 int uexpr_link
= node
->u
.unary_expression
.link
;
750 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_UNSIGNED_CONSTANT
||
751 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
753 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid constant unsigned integer.");
758 *value
= node
->u
.unary_expression
.u
.unsigned_constant
;
766 static int is_unary_signed(struct bt_list_head
*head
)
769 struct ctf_node
*node
;
771 bt_list_for_each_entry (node
, head
, siblings
) {
772 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
776 if (node
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
) {
784 static int get_unary_signed(struct bt_list_head
*head
, int64_t *value
)
788 struct ctf_node
*node
;
790 bt_list_for_each_entry (node
, head
, siblings
) {
791 int uexpr_type
= node
->u
.unary_expression
.type
;
792 int uexpr_link
= node
->u
.unary_expression
.link
;
793 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
794 (uexpr_type
!= UNARY_UNSIGNED_CONSTANT
&& uexpr_type
!= UNARY_SIGNED_CONSTANT
) ||
795 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
801 switch (uexpr_type
) {
802 case UNARY_UNSIGNED_CONSTANT
:
803 *value
= (int64_t) node
->u
.unary_expression
.u
.unsigned_constant
;
805 case UNARY_SIGNED_CONSTANT
:
806 *value
= node
->u
.unary_expression
.u
.signed_constant
;
820 static int get_unary_uuid(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
823 return ctf_ast_get_unary_uuid(head
, uuid
, ctx
->log_cfg
.log_level
, ctx
->log_cfg
.self_comp
);
826 static int get_boolean(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*unary_expr
)
830 if (unary_expr
->type
!= NODE_UNARY_EXPRESSION
) {
831 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
, "Expecting unary expression: node-type=%d",
837 switch (unary_expr
->u
.unary_expression
.type
) {
838 case UNARY_UNSIGNED_CONSTANT
:
839 ret
= (unary_expr
->u
.unary_expression
.u
.unsigned_constant
!= 0);
841 case UNARY_SIGNED_CONSTANT
:
842 ret
= (unary_expr
->u
.unary_expression
.u
.signed_constant
!= 0);
846 const char *str
= unary_expr
->u
.unary_expression
.u
.string
;
848 if (strcmp(str
, "true") == 0 || strcmp(str
, "TRUE") == 0) {
850 } else if (strcmp(str
, "false") == 0 || strcmp(str
, "FALSE") == 0) {
853 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
, "Unexpected boolean value: value=\"%s\"",
861 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
862 "Unexpected unary expression type: node-type=%d",
863 unary_expr
->u
.unary_expression
.type
);
872 static enum ctf_byte_order
byte_order_from_unary_expr(struct ctf_visitor_generate_ir
*ctx
,
873 struct ctf_node
*unary_expr
)
876 enum ctf_byte_order bo
= CTF_BYTE_ORDER_UNKNOWN
;
878 if (unary_expr
->u
.unary_expression
.type
!= UNARY_STRING
) {
879 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
880 unary_expr
, "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
884 str
= unary_expr
->u
.unary_expression
.u
.string
;
886 if (strcmp(str
, "be") == 0 || strcmp(str
, "network") == 0) {
887 bo
= CTF_BYTE_ORDER_BIG
;
888 } else if (strcmp(str
, "le") == 0) {
889 bo
= CTF_BYTE_ORDER_LITTLE
;
890 } else if (strcmp(str
, "native") == 0) {
891 bo
= CTF_BYTE_ORDER_DEFAULT
;
893 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
895 "Unexpected \"byte_order\" attribute value: "
896 "expecting `be`, `le`, `network`, or `native`: value=\"%s\"",
905 static enum ctf_byte_order
get_real_byte_order(struct ctf_visitor_generate_ir
*ctx
,
906 struct ctf_node
*uexpr
)
908 enum ctf_byte_order bo
= byte_order_from_unary_expr(ctx
, uexpr
);
910 if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
911 bo
= ctx
->ctf_tc
->default_byte_order
;
917 static int is_align_valid(uint64_t align
)
919 return (align
!= 0) && !(align
& (align
- UINT64_C(1)));
922 static int get_class_specifier_name(struct ctf_visitor_generate_ir
*ctx
,
923 struct ctf_node
*cls_specifier
, GString
*str
)
927 if (cls_specifier
->type
!= NODE_TYPE_SPECIFIER
) {
928 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
, "Unexpected node type: node-type=%d",
929 cls_specifier
->type
);
934 switch (cls_specifier
->u
.field_class_specifier
.type
) {
936 g_string_append(str
, "void");
939 g_string_append(str
, "char");
942 g_string_append(str
, "short");
945 g_string_append(str
, "int");
948 g_string_append(str
, "long");
951 g_string_append(str
, "float");
953 case TYPESPEC_DOUBLE
:
954 g_string_append(str
, "double");
956 case TYPESPEC_SIGNED
:
957 g_string_append(str
, "signed");
959 case TYPESPEC_UNSIGNED
:
960 g_string_append(str
, "unsigned");
963 g_string_append(str
, "bool");
965 case TYPESPEC_COMPLEX
:
966 g_string_append(str
, "_Complex");
968 case TYPESPEC_IMAGINARY
:
969 g_string_append(str
, "_Imaginary");
972 g_string_append(str
, "const");
974 case TYPESPEC_ID_TYPE
:
975 if (cls_specifier
->u
.field_class_specifier
.id_type
) {
976 g_string_append(str
, cls_specifier
->u
.field_class_specifier
.id_type
);
979 case TYPESPEC_STRUCT
:
981 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
983 if (!node
->u
._struct
.name
) {
984 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty structure field class name.");
989 g_string_append(str
, "struct ");
990 g_string_append(str
, node
->u
._struct
.name
);
993 case TYPESPEC_VARIANT
:
995 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
997 if (!node
->u
.variant
.name
) {
998 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty variant field class name.");
1003 g_string_append(str
, "variant ");
1004 g_string_append(str
, node
->u
.variant
.name
);
1009 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1011 if (!node
->u
._enum
.enum_id
) {
1012 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1013 node
, "Unexpected empty enumeration field class (`enum`) name.");
1018 g_string_append(str
, "enum ");
1019 g_string_append(str
, node
->u
._enum
.enum_id
);
1022 case TYPESPEC_FLOATING_POINT
:
1023 case TYPESPEC_INTEGER
:
1024 case TYPESPEC_STRING
:
1026 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
->u
.field_class_specifier
.node
,
1027 "Unexpected field class specifier type: %d",
1028 cls_specifier
->u
.field_class_specifier
.type
);
1037 static int get_class_specifier_list_name(struct ctf_visitor_generate_ir
*ctx
,
1038 struct ctf_node
*cls_specifier_list
, GString
*str
)
1041 struct ctf_node
*iter
;
1042 int alias_item_nr
= 0;
1043 struct bt_list_head
*head
= &cls_specifier_list
->u
.field_class_specifier_list
.head
;
1045 bt_list_for_each_entry (iter
, head
, siblings
) {
1046 if (alias_item_nr
!= 0) {
1047 g_string_append(str
, " ");
1051 ret
= get_class_specifier_name(ctx
, iter
, str
);
1061 static GQuark
create_class_alias_identifier(struct ctf_visitor_generate_ir
*ctx
,
1062 struct ctf_node
*cls_specifier_list
,
1063 struct ctf_node
*node_field_class_declarator
)
1069 struct ctf_node
*iter
;
1070 struct bt_list_head
*pointers
= &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1072 str
= g_string_new("");
1073 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
1075 g_string_free(str
, TRUE
);
1079 bt_list_for_each_entry (iter
, pointers
, siblings
) {
1080 g_string_append(str
, " *");
1082 if (iter
->u
.pointer
.const_qualifier
) {
1083 g_string_append(str
, " const");
1087 str_c
= g_string_free(str
, FALSE
);
1088 qalias
= g_quark_from_string(str_c
);
1095 static int visit_field_class_declarator(struct ctf_visitor_generate_ir
*ctx
,
1096 struct ctf_node
*cls_specifier_list
, GQuark
*field_name
,
1097 struct ctf_node
*node_field_class_declarator
,
1098 struct ctf_field_class
**field_decl
,
1099 struct ctf_field_class
*nested_decl
)
1102 * During this whole function, nested_decl is always OURS,
1103 * whereas field_decl is an output which we create, but
1104 * belongs to the caller (it is moved).
1109 /* Validate field class declarator node */
1110 if (node_field_class_declarator
) {
1111 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_UNKNOWN
) {
1112 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1113 node_field_class_declarator
, "Unexpected field class declarator type: type=%d",
1114 node_field_class_declarator
->u
.field_class_declarator
.type
);
1119 /* TODO: GCC bitfields not supported yet */
1120 if (node_field_class_declarator
->u
.field_class_declarator
.bitfield_len
!= NULL
) {
1121 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1122 "GCC bitfields are not supported as of this version.");
1128 /* Find the right nested declaration if not provided */
1130 struct bt_list_head
*pointers
=
1131 &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1133 if (node_field_class_declarator
&& !bt_list_empty(pointers
)) {
1137 * If we have a pointer declarator, it HAS to
1138 * be present in the field class aliases (else
1142 create_class_alias_identifier(ctx
, cls_specifier_list
, node_field_class_declarator
);
1143 nested_decl
= ctx_decl_scope_lookup_alias(ctx
, ctx
->current_scope
,
1144 g_quark_to_string(qalias
), -1, true);
1146 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1147 "Cannot find class alias: name=\"%s\"",
1148 g_quark_to_string(qalias
));
1153 if (nested_decl
->type
== CTF_FIELD_CLASS_TYPE_INT
) {
1154 /* Pointer: force integer's base to 16 */
1155 struct ctf_field_class_int
*int_fc
= ctf_field_class_as_int(nested_decl
);
1157 int_fc
->disp_base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
1160 ret
= visit_field_class_specifier_list(ctx
, cls_specifier_list
, &nested_decl
);
1162 BT_ASSERT(!nested_decl
);
1168 BT_ASSERT(nested_decl
);
1170 if (!node_field_class_declarator
) {
1171 *field_decl
= nested_decl
;
1176 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_ID
) {
1177 if (node_field_class_declarator
->u
.field_class_declarator
.u
.id
) {
1178 const char *id
= node_field_class_declarator
->u
.field_class_declarator
.u
.id
;
1180 *field_name
= g_quark_from_string(id
);
1185 *field_decl
= nested_decl
;
1189 struct ctf_node
*first
;
1190 struct ctf_field_class
*decl
= NULL
;
1191 struct ctf_field_class
*outer_field_decl
= NULL
;
1192 struct bt_list_head
*length
=
1193 &node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.length
;
1195 /* Create array/sequence, pass nested_decl as child */
1196 if (bt_list_empty(length
)) {
1197 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1198 "Expecting length field reference or value.");
1203 first
= _BT_LIST_FIRST_ENTRY(length
, struct ctf_node
, siblings
);
1204 if (first
->type
!= NODE_UNARY_EXPRESSION
) {
1205 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type=%d",
1211 switch (first
->u
.unary_expression
.type
) {
1212 case UNARY_UNSIGNED_CONSTANT
:
1214 struct ctf_field_class_array
*array_decl
= NULL
;
1216 array_decl
= ctf_field_class_array_create();
1217 BT_ASSERT(array_decl
);
1218 array_decl
->length
= first
->u
.unary_expression
.u
.unsigned_constant
;
1219 array_decl
->base
.elem_fc
= nested_decl
;
1221 decl
= &array_decl
->base
.base
;
1226 /* Lookup unsigned integer definition, create seq. */
1227 struct ctf_field_class_sequence
*seq_decl
= NULL
;
1228 char *length_name
= ctf_ast_concatenate_unary_strings(length
);
1231 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1232 "Cannot concatenate unary strings.");
1237 if (strncmp(length_name
, "env.", 4) == 0) {
1238 /* This is, in fact, an array */
1239 const char *env_entry_name
= &length_name
[4];
1240 struct ctf_trace_class_env_entry
*env_entry
=
1241 ctf_trace_class_borrow_env_entry_by_name(ctx
->ctf_tc
, env_entry_name
);
1242 struct ctf_field_class_array
*array_decl
;
1245 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1246 "Cannot find environment entry: "
1253 if (env_entry
->type
!= CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
) {
1254 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1255 "Wrong environment entry type "
1256 "(expecting integer): "
1263 if (env_entry
->value
.i
< 0) {
1264 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1265 "Invalid, negative array length: "
1266 "env-entry-name=\"%s\", "
1268 env_entry_name
, env_entry
->value
.i
);
1273 array_decl
= ctf_field_class_array_create();
1274 BT_ASSERT(array_decl
);
1275 array_decl
->length
= (uint64_t) env_entry
->value
.i
;
1276 array_decl
->base
.elem_fc
= nested_decl
;
1278 decl
= &array_decl
->base
.base
;
1280 seq_decl
= ctf_field_class_sequence_create();
1281 BT_ASSERT(seq_decl
);
1282 seq_decl
->base
.elem_fc
= nested_decl
;
1284 g_string_assign(seq_decl
->length_ref
, length_name
);
1285 decl
= &seq_decl
->base
.base
;
1288 g_free(length_name
);
1296 BT_ASSERT(!nested_decl
);
1298 BT_ASSERT(!*field_decl
);
1301 * At this point, we found the next nested declaration.
1302 * We currently own this (and lost the ownership of
1303 * nested_decl in the meantime). Pass this next
1304 * nested declaration as the content of the outer
1305 * container, MOVING its ownership.
1307 ret
= visit_field_class_declarator(
1308 ctx
, cls_specifier_list
, field_name
,
1309 node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.field_class_declarator
,
1310 &outer_field_decl
, decl
);
1313 BT_ASSERT(!outer_field_decl
);
1318 BT_ASSERT(outer_field_decl
);
1319 *field_decl
= outer_field_decl
;
1320 outer_field_decl
= NULL
;
1323 BT_ASSERT(*field_decl
);
1327 ctf_field_class_destroy(*field_decl
);
1335 ctf_field_class_destroy(nested_decl
);
1340 static int visit_struct_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1341 struct ctf_field_class_struct
*struct_decl
,
1342 struct ctf_node
*cls_specifier_list
,
1343 struct bt_list_head
*field_class_declarators
)
1346 struct ctf_node
*iter
;
1347 struct ctf_field_class
*field_decl
= NULL
;
1349 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1352 const char *field_name
;
1354 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1357 BT_ASSERT(!field_decl
);
1358 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1359 "Cannot visit field class declarator: ret=%d", ret
);
1363 BT_ASSERT(field_decl
);
1364 field_name
= g_quark_to_string(qfield_name
);
1366 /* Check if field with same name already exists */
1367 if (ctf_field_class_struct_borrow_member_by_name(struct_decl
, field_name
)) {
1368 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1369 "Duplicate field in structure field class: "
1370 "field-name=\"%s\"",
1376 /* Add field to structure */
1377 ctf_field_class_struct_append_member(struct_decl
, field_name
, field_decl
);
1384 ctf_field_class_destroy(field_decl
);
1389 static int visit_variant_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1390 struct ctf_field_class_variant
*variant_decl
,
1391 struct ctf_node
*cls_specifier_list
,
1392 struct bt_list_head
*field_class_declarators
)
1395 struct ctf_node
*iter
;
1396 struct ctf_field_class
*field_decl
= NULL
;
1398 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1401 const char *field_name
;
1403 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1406 BT_ASSERT(!field_decl
);
1407 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1408 "Cannot visit field class declarator: ret=%d", ret
);
1412 BT_ASSERT(field_decl
);
1413 field_name
= g_quark_to_string(qfield_name
);
1415 /* Check if field with same name already exists */
1416 if (ctf_field_class_variant_borrow_option_by_name(variant_decl
, field_name
)) {
1417 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1418 "Duplicate field in variant field class: "
1419 "field-name=\"%s\"",
1425 /* Add field to structure */
1426 ctf_field_class_variant_append_option(variant_decl
, field_name
, field_decl
);
1433 ctf_field_class_destroy(field_decl
);
1438 static int visit_field_class_def(struct ctf_visitor_generate_ir
*ctx
,
1439 struct ctf_node
*cls_specifier_list
,
1440 struct bt_list_head
*field_class_declarators
)
1444 struct ctf_node
*iter
;
1445 struct ctf_field_class
*class_decl
= NULL
;
1447 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1448 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qidentifier
, iter
, &class_decl
,
1451 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit field class declarator: ret=%d",
1457 /* Do not allow field class def and alias of untagged variants */
1458 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1459 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1461 if (var_fc
->tag_path
.path
->len
== 0) {
1462 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1463 iter
, "Type definition of untagged variant field class is not allowed.");
1469 ret
= ctx_decl_scope_register_alias(ctx
, ctx
->current_scope
, g_quark_to_string(qidentifier
),
1472 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot register field class alias: name=\"%s\"",
1473 g_quark_to_string(qidentifier
));
1479 ctf_field_class_destroy(class_decl
);
1484 static int visit_field_class_alias(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*target
,
1485 struct ctf_node
*alias
)
1489 struct ctf_node
*node
;
1490 GQuark qdummy_field_name
;
1491 struct ctf_field_class
*class_decl
= NULL
;
1493 /* Create target field class */
1494 if (bt_list_empty(&target
->u
.field_class_alias_target
.field_class_declarators
)) {
1497 node
= _BT_LIST_FIRST_ENTRY(&target
->u
.field_class_alias_target
.field_class_declarators
,
1498 struct ctf_node
, siblings
);
1501 ret
= visit_field_class_declarator(
1502 ctx
, target
->u
.field_class_alias_target
.field_class_specifier_list
, &qdummy_field_name
,
1503 node
, &class_decl
, NULL
);
1505 BT_ASSERT(!class_decl
);
1506 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot visit field class declarator: ret=%d", ret
);
1510 /* Do not allow field class def and alias of untagged variants */
1511 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1512 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1514 if (var_fc
->tag_path
.path
->len
== 0) {
1515 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1516 target
, "Type definition of untagged variant field class is not allowed.");
1523 * The semantic validator does not check whether the target is
1524 * abstract or not (if it has an identifier). Check it here.
1526 if (qdummy_field_name
!= 0) {
1527 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target
, "Expecting empty identifier: id=\"%s\"",
1528 g_quark_to_string(qdummy_field_name
));
1533 /* Create alias identifier */
1534 node
= _BT_LIST_FIRST_ENTRY(&alias
->u
.field_class_alias_name
.field_class_declarators
,
1535 struct ctf_node
, siblings
);
1536 qalias
= create_class_alias_identifier(
1537 ctx
, alias
->u
.field_class_alias_name
.field_class_specifier_list
, node
);
1538 ret
= ctx_decl_scope_register_alias(ctx
, ctx
->current_scope
, g_quark_to_string(qalias
),
1541 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot register class alias: name=\"%s\"",
1542 g_quark_to_string(qalias
));
1547 ctf_field_class_destroy(class_decl
);
1552 static int visit_struct_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
1553 struct ctf_field_class_struct
*struct_decl
)
1557 switch (entry_node
->type
) {
1559 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1560 &entry_node
->u
.field_class_def
.field_class_declarators
);
1562 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1563 entry_node
, "Cannot add field class found in structure field class: ret=%d", ret
);
1567 case NODE_TYPEALIAS
:
1568 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1569 entry_node
->u
.field_class_alias
.alias
);
1571 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1572 entry_node
, "Cannot add field class alias found in structure field class: ret=%d",
1577 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1579 ret
= visit_struct_decl_field(
1581 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1582 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1588 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
1598 static int visit_variant_decl_entry(struct ctf_visitor_generate_ir
*ctx
,
1599 struct ctf_node
*entry_node
,
1600 struct ctf_field_class_variant
*variant_decl
)
1604 switch (entry_node
->type
) {
1606 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1607 &entry_node
->u
.field_class_def
.field_class_declarators
);
1609 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1610 entry_node
, "Cannot add field class found in variant field class: ret=%d", ret
);
1614 case NODE_TYPEALIAS
:
1615 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1616 entry_node
->u
.field_class_alias
.alias
);
1618 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1619 entry_node
, "Cannot add field class alias found in variant field class: ret=%d",
1624 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1626 ret
= visit_variant_decl_field(
1628 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1629 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1635 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
1645 static int visit_struct_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1646 struct bt_list_head
*decl_list
, int has_body
,
1647 struct bt_list_head
*min_align
,
1648 struct ctf_field_class_struct
**struct_decl
)
1652 BT_ASSERT(struct_decl
);
1653 *struct_decl
= NULL
;
1655 /* For named struct (without body), lookup in declaration scope */
1658 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1659 "Bodyless structure field class: missing name.");
1664 *struct_decl
= ctx_decl_scope_lookup_struct(ctx
, ctx
->current_scope
, name
, -1, true);
1665 if (!*struct_decl
) {
1666 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1667 "Cannot find structure field class: name=\"struct %s\"", name
);
1672 struct ctf_node
*entry_node
;
1673 uint64_t min_align_value
= 0;
1676 if (ctx_decl_scope_lookup_struct(ctx
, ctx
->current_scope
, name
, 1, false)) {
1677 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1678 "Structure field class already declared in local scope: "
1679 "name=\"struct %s\"",
1686 if (!bt_list_empty(min_align
)) {
1687 ret
= get_unary_unsigned(ctx
, min_align
, &min_align_value
);
1689 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1690 "Unexpected unary expression for structure field class's `align` attribute: "
1697 *struct_decl
= ctf_field_class_struct_create();
1698 BT_ASSERT(*struct_decl
);
1700 if (min_align_value
!= 0) {
1701 (*struct_decl
)->base
.alignment
= min_align_value
;
1704 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1706 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1707 ret
= visit_struct_decl_entry(ctx
, entry_node
, *struct_decl
);
1709 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1710 "Cannot visit structure field class entry: "
1721 ret
= ctx_decl_scope_register_struct(ctx
, ctx
->current_scope
, name
, *struct_decl
);
1723 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1724 "Cannot register structure field class in declaration scope: "
1725 "name=\"struct %s\", ret=%d",
1735 ctf_field_class_destroy(&(*struct_decl
)->base
);
1736 *struct_decl
= NULL
;
1740 static int visit_variant_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1741 const char *tag
, struct bt_list_head
*decl_list
, int has_body
,
1742 struct ctf_field_class_variant
**variant_decl
)
1745 struct ctf_field_class_variant
*untagged_variant_decl
= NULL
;
1747 BT_ASSERT(variant_decl
);
1748 *variant_decl
= NULL
;
1750 /* For named variant (without body), lookup in declaration scope */
1753 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name.");
1758 untagged_variant_decl
=
1759 ctx_decl_scope_lookup_variant(ctx
, ctx
->current_scope
, name
, -1, true);
1760 if (!untagged_variant_decl
) {
1761 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1762 "Cannot find variant field class: name=\"variant %s\"", name
);
1767 struct ctf_node
*entry_node
;
1770 if (ctx_decl_scope_lookup_variant(ctx
, ctx
->current_scope
, name
, 1, false)) {
1771 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1772 "Variant field class already declared in local scope: "
1773 "name=\"variant %s\"",
1780 untagged_variant_decl
= ctf_field_class_variant_create();
1781 BT_ASSERT(untagged_variant_decl
);
1782 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1784 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1785 ret
= visit_variant_decl_entry(ctx
, entry_node
, untagged_variant_decl
);
1787 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1788 "Cannot visit variant field class entry: "
1799 ret
= ctx_decl_scope_register_variant(ctx
, ctx
->current_scope
, name
,
1800 untagged_variant_decl
);
1802 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1803 "Cannot register variant field class in declaration scope: "
1804 "name=\"variant %s\", ret=%d",
1812 * If tagged, create tagged variant and return; otherwise
1813 * return untagged variant.
1816 *variant_decl
= untagged_variant_decl
;
1817 untagged_variant_decl
= NULL
;
1820 * At this point, we have a fresh untagged variant; nobody
1821 * else owns it. Set its tag now.
1823 g_string_assign(untagged_variant_decl
->tag_ref
, tag
);
1824 *variant_decl
= untagged_variant_decl
;
1825 untagged_variant_decl
= NULL
;
1828 BT_ASSERT(!untagged_variant_decl
);
1829 BT_ASSERT(*variant_decl
);
1833 ctf_field_class_destroy(&untagged_variant_decl
->base
);
1834 untagged_variant_decl
= NULL
;
1835 ctf_field_class_destroy(&(*variant_decl
)->base
);
1836 *variant_decl
= NULL
;
1850 static int visit_enum_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*enumerator
,
1851 struct ctf_field_class_enum
*enum_decl
, struct uori
*last
)
1855 struct ctf_node
*iter
;
1856 struct uori start
= {
1870 const char *label
= enumerator
->u
.enumerator
.id
;
1871 struct bt_list_head
*values
= &enumerator
->u
.enumerator
.values
;
1873 bt_list_for_each_entry (iter
, values
, siblings
) {
1874 struct uori
*target
;
1876 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
1877 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1878 "Wrong expression for enumeration field class label: "
1879 "node-type=%d, label=\"%s\"",
1891 switch (iter
->u
.unary_expression
.type
) {
1892 case UNARY_SIGNED_CONSTANT
:
1893 target
->is_signed
= true;
1894 target
->value
.i
= iter
->u
.unary_expression
.u
.signed_constant
;
1896 case UNARY_UNSIGNED_CONSTANT
:
1897 target
->is_signed
= false;
1898 target
->value
.u
= iter
->u
.unary_expression
.u
.unsigned_constant
;
1901 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1902 "Invalid enumeration field class entry: "
1903 "expecting constant signed or unsigned integer: "
1904 "node-type=%d, label=\"%s\"",
1905 iter
->u
.unary_expression
.type
, label
);
1911 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1912 iter
, "Invalid enumeration field class entry: label=\"%s\"", label
);
1928 if (end
.is_signed
) {
1929 last
->value
.i
= end
.value
.i
+ 1;
1931 last
->value
.u
= end
.value
.u
+ 1;
1934 ctf_field_class_enum_map_range(enum_decl
, label
, start
.value
.u
, end
.value
.u
);
1941 static int visit_enum_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1942 struct ctf_node
*container_cls
, struct bt_list_head
*enumerator_list
,
1943 int has_body
, struct ctf_field_class_enum
**enum_decl
)
1947 struct ctf_field_class_int
*integer_decl
= NULL
;
1949 BT_ASSERT(enum_decl
);
1952 /* For named enum (without body), lookup in declaration scope */
1955 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1956 "Bodyless enumeration field class: missing name.");
1961 *enum_decl
= ctx_decl_scope_lookup_enum(ctx
, ctx
->current_scope
, name
, -1, true);
1963 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: "
1970 struct ctf_node
*iter
;
1971 struct uori last_value
= {
1980 if (ctx_decl_scope_lookup_enum(ctx
, ctx
->current_scope
, name
, 1, false)) {
1981 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1982 "Enumeration field class already declared in local scope: "
1990 if (!container_cls
) {
1991 integer_decl
= ctf_field_class_as_int(
1992 ctx_decl_scope_lookup_alias(ctx
, ctx
->current_scope
, "int", -1, true));
1993 if (!integer_decl
) {
1994 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1995 "Cannot find implicit `int` field class alias for enumeration field class.");
2000 ctf_field_class
*decl
;
2002 ret
= visit_field_class_declarator(ctx
, container_cls
, &qdummy_id
, NULL
, &decl
, NULL
);
2009 integer_decl
= ctf_field_class_as_int(decl
);
2012 BT_ASSERT(integer_decl
);
2014 if (integer_decl
->base
.base
.type
!= CTF_FIELD_CLASS_TYPE_INT
) {
2015 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2016 "Container field class for enumeration field class is not an integer field class: "
2018 integer_decl
->base
.base
.type
);
2023 *enum_decl
= ctf_field_class_enum_create();
2024 BT_ASSERT(*enum_decl
);
2025 (*enum_decl
)->base
.base
.base
.alignment
= integer_decl
->base
.base
.alignment
;
2026 ctf_field_class_int_copy_content(&(*enum_decl
)->base
, integer_decl
);
2027 last_value
.is_signed
= (*enum_decl
)->base
.is_signed
;
2029 bt_list_for_each_entry (iter
, enumerator_list
, siblings
) {
2030 ret
= visit_enum_decl_entry(ctx
, iter
, *enum_decl
, &last_value
);
2032 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
2033 "Cannot visit enumeration field class entry: "
2041 ret
= ctx_decl_scope_register_enum(ctx
, ctx
->current_scope
, name
, *enum_decl
);
2043 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2044 "Cannot register enumeration field class in declaration scope: "
2055 ctf_field_class_destroy(&(*enum_decl
)->base
.base
.base
);
2059 ctf_field_class_destroy(&integer_decl
->base
.base
);
2060 integer_decl
= NULL
;
2064 static int visit_field_class_specifier(struct ctf_visitor_generate_ir
*ctx
,
2065 struct ctf_node
*cls_specifier_list
,
2066 struct ctf_field_class
**decl
)
2069 GString
*str
= NULL
;
2072 str
= g_string_new("");
2073 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
2075 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2076 cls_specifier_list
, "Cannot get field class specifier list's name: ret=%d", ret
);
2080 *decl
= ctx_decl_scope_lookup_alias(ctx
, ctx
->current_scope
, str
->str
, -1, true);
2082 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2083 "Cannot find field class alias: name=\"%s\"", str
->str
);
2091 ctf_field_class_destroy(*decl
);
2096 g_string_free(str
, TRUE
);
2102 static int visit_integer_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2103 struct ctf_field_class_int
**integer_decl
)
2108 struct ctf_node
*expression
;
2109 uint64_t alignment
= 0, size
= 0;
2110 struct ctf_clock_class
*mapped_clock_class
= NULL
;
2111 enum ctf_encoding encoding
= CTF_ENCODING_NONE
;
2112 bt_field_class_integer_preferred_display_base base
=
2113 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2114 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2116 *integer_decl
= NULL
;
2118 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2119 struct ctf_node
*left
, *right
;
2121 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2123 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2125 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2126 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2127 left
->u
.unary_expression
.type
);
2132 if (strcmp(left
->u
.unary_expression
.u
.string
, "signed") == 0) {
2133 if (_IS_SET(&set
, _INTEGER_SIGNED_SET
)) {
2134 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "signed", "integer field class");
2139 signedness
= get_boolean(ctx
, right
);
2140 if (signedness
< 0) {
2141 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2143 "Invalid boolean value for integer field class's `signed` attribute: "
2150 _SET(&set
, _INTEGER_SIGNED_SET
);
2151 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2152 if (_IS_SET(&set
, _INTEGER_BYTE_ORDER_SET
)) {
2153 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order", "integer field class");
2158 byte_order
= get_real_byte_order(ctx
, right
);
2159 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2160 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2162 "Invalid `byte_order` attribute in integer field class: "
2169 _SET(&set
, _INTEGER_BYTE_ORDER_SET
);
2170 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "size") == 0) {
2171 if (_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2172 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "size", "integer field class");
2177 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2178 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2179 "Invalid `size` attribute in integer field class: "
2180 "expecting unsigned constant integer: "
2182 right
->u
.unary_expression
.type
);
2187 size
= right
->u
.unary_expression
.u
.unsigned_constant
;
2189 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2190 "Invalid `size` attribute in integer field class: "
2191 "expecting positive constant integer: "
2196 } else if (size
> 64) {
2197 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2199 "Invalid `size` attribute in integer field class: "
2200 "integer fields over 64 bits are not supported as of this version: "
2207 _SET(&set
, _INTEGER_SIZE_SET
);
2208 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2209 if (_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2210 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align", "integer field class");
2215 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2216 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2217 "Invalid `align` attribute in integer field class: "
2218 "expecting unsigned constant integer: "
2220 right
->u
.unary_expression
.type
);
2225 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2226 if (!is_align_valid(alignment
)) {
2227 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2228 "Invalid `align` attribute in integer field class: "
2229 "expecting power of two: "
2236 _SET(&set
, _INTEGER_ALIGN_SET
);
2237 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "base") == 0) {
2238 if (_IS_SET(&set
, _INTEGER_BASE_SET
)) {
2239 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "base", "integer field class");
2244 switch (right
->u
.unary_expression
.type
) {
2245 case UNARY_UNSIGNED_CONSTANT
:
2247 uint64_t constant
= right
->u
.unary_expression
.u
.unsigned_constant
;
2251 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2254 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2257 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2260 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2263 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2265 "Invalid `base` attribute in integer field class: "
2267 right
->u
.unary_expression
.u
.unsigned_constant
);
2276 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2278 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2280 "Unexpected unary expression for integer field class's `base` attribute.");
2285 if (strcmp(s_right
, "decimal") == 0 || strcmp(s_right
, "dec") == 0 ||
2286 strcmp(s_right
, "d") == 0 || strcmp(s_right
, "i") == 0 ||
2287 strcmp(s_right
, "u") == 0) {
2288 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2289 } else if (strcmp(s_right
, "hexadecimal") == 0 || strcmp(s_right
, "hex") == 0 ||
2290 strcmp(s_right
, "x") == 0 || strcmp(s_right
, "X") == 0 ||
2291 strcmp(s_right
, "p") == 0) {
2292 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2293 } else if (strcmp(s_right
, "octal") == 0 || strcmp(s_right
, "oct") == 0 ||
2294 strcmp(s_right
, "o") == 0) {
2295 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2296 } else if (strcmp(s_right
, "binary") == 0 || strcmp(s_right
, "b") == 0) {
2297 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2299 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2301 "Unexpected unary expression for integer field class's `base` attribute: "
2313 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2314 right
, "Invalid `base` attribute in integer field class: "
2315 "expecting unsigned constant integer or unary string.");
2320 _SET(&set
, _INTEGER_BASE_SET
);
2321 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2324 if (_IS_SET(&set
, _INTEGER_ENCODING_SET
)) {
2325 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "integer field class");
2330 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2331 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2332 right
, "Invalid `encoding` attribute in integer field class: "
2333 "expecting unary string.");
2338 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2340 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2342 "Unexpected unary expression for integer field class's `encoding` attribute.");
2347 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2348 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2349 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2350 encoding
= CTF_ENCODING_UTF8
;
2351 } else if (strcmp(s_right
, "none") == 0) {
2352 encoding
= CTF_ENCODING_NONE
;
2354 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2356 "Invalid `encoding` attribute in integer field class: "
2357 "unknown encoding: encoding=\"%s\"",
2365 _SET(&set
, _INTEGER_ENCODING_SET
);
2366 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "map") == 0) {
2367 const char *clock_name
;
2369 if (_IS_SET(&set
, _INTEGER_MAP_SET
)) {
2370 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "map", "integer field class");
2375 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2376 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2377 "Invalid `map` attribute in integer field class: "
2378 "expecting unary string.");
2383 clock_name
= get_map_clock_name_value(&expression
->u
.ctf_expression
.right
);
2386 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2389 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2391 "Unexpected unary expression for integer field class's `map` attribute.");
2396 _BT_COMP_LOGE_NODE(right
,
2397 "Invalid `map` attribute in integer field class: "
2398 "cannot find clock class at this point: name=\"%s\"",
2400 _SET(&set
, _INTEGER_MAP_SET
);
2405 mapped_clock_class
=
2406 ctf_trace_class_borrow_clock_class_by_name(ctx
->ctf_tc
, clock_name
);
2407 if (!mapped_clock_class
) {
2408 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2410 "Invalid `map` attribute in integer field class: "
2411 "cannot find clock class at this point: name=\"%s\"",
2417 _SET(&set
, _INTEGER_MAP_SET
);
2419 _BT_COMP_LOGW_NODE(left
,
2420 "Unknown attribute in integer field class: "
2422 left
->u
.unary_expression
.u
.string
);
2426 if (!_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2427 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2428 "Missing `size` attribute in integer field class.");
2433 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2434 if (size
% CHAR_BIT
) {
2435 /* Bit-packed alignment */
2438 /* Byte-packed alignment */
2439 alignment
= CHAR_BIT
;
2443 *integer_decl
= ctf_field_class_int_create();
2444 BT_ASSERT(*integer_decl
);
2445 (*integer_decl
)->base
.base
.alignment
= alignment
;
2446 (*integer_decl
)->base
.byte_order
= byte_order
;
2447 (*integer_decl
)->base
.size
= size
;
2448 (*integer_decl
)->is_signed
= (signedness
> 0);
2449 (*integer_decl
)->disp_base
= base
;
2450 (*integer_decl
)->encoding
= encoding
;
2451 (*integer_decl
)->mapped_clock_class
= mapped_clock_class
;
2455 ctf_field_class_destroy(&(*integer_decl
)->base
.base
);
2456 *integer_decl
= NULL
;
2460 static int visit_floating_point_number_decl(struct ctf_visitor_generate_ir
*ctx
,
2461 struct bt_list_head
*expressions
,
2462 struct ctf_field_class_float
**float_decl
)
2466 struct ctf_node
*expression
;
2467 uint64_t alignment
= 1, exp_dig
= 0, mant_dig
= 0;
2468 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2472 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2473 struct ctf_node
*left
, *right
;
2475 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2477 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2479 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2480 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2481 left
->u
.unary_expression
.type
);
2486 if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2487 if (_IS_SET(&set
, _FLOAT_BYTE_ORDER_SET
)) {
2488 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order",
2489 "floating point number field class");
2494 byte_order
= get_real_byte_order(ctx
, right
);
2495 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2496 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2498 "Invalid `byte_order` attribute in floating point number field class: "
2505 _SET(&set
, _FLOAT_BYTE_ORDER_SET
);
2506 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "exp_dig") == 0) {
2507 if (_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2508 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "exp_dig",
2509 "floating point number field class");
2514 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2515 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2517 "Invalid `exp_dig` attribute in floating point number field class: "
2518 "expecting unsigned constant integer: "
2520 right
->u
.unary_expression
.type
);
2525 exp_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2526 _SET(&set
, _FLOAT_EXP_DIG_SET
);
2527 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "mant_dig") == 0) {
2528 if (_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2529 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "mant_dig",
2530 "floating point number field class");
2535 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2536 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2538 "Invalid `mant_dig` attribute in floating point number field class: "
2539 "expecting unsigned constant integer: "
2541 right
->u
.unary_expression
.type
);
2546 mant_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2547 _SET(&set
, _FLOAT_MANT_DIG_SET
);
2548 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2549 if (_IS_SET(&set
, _FLOAT_ALIGN_SET
)) {
2550 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align",
2551 "floating point number field class");
2556 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2557 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2559 "Invalid `align` attribute in floating point number field class: "
2560 "expecting unsigned constant integer: "
2562 right
->u
.unary_expression
.type
);
2567 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2569 if (!is_align_valid(alignment
)) {
2570 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2572 "Invalid `align` attribute in floating point number field class: "
2573 "expecting power of two: "
2580 _SET(&set
, _FLOAT_ALIGN_SET
);
2582 _BT_COMP_LOGW_NODE(left
,
2583 "Unknown attribute in floating point number field class: "
2585 left
->u
.unary_expression
.u
.string
);
2589 if (!_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2590 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2591 "Missing `mant_dig` attribute in floating point number field class.");
2596 if (!_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2597 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2598 "Missing `exp_dig` attribute in floating point number field class.");
2603 if (mant_dig
!= 24 && mant_dig
!= 53) {
2604 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53.");
2609 if (mant_dig
== 24 && exp_dig
!= 8) {
2610 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2611 "`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2616 if (mant_dig
== 53 && exp_dig
!= 11) {
2617 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2618 "`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2623 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2624 if ((mant_dig
+ exp_dig
) % CHAR_BIT
) {
2625 /* Bit-packed alignment */
2628 /* Byte-packed alignment */
2629 alignment
= CHAR_BIT
;
2633 *float_decl
= ctf_field_class_float_create();
2634 BT_ASSERT(*float_decl
);
2635 (*float_decl
)->base
.base
.alignment
= alignment
;
2636 (*float_decl
)->base
.byte_order
= byte_order
;
2637 (*float_decl
)->base
.size
= mant_dig
+ exp_dig
;
2641 ctf_field_class_destroy(&(*float_decl
)->base
.base
);
2646 static int visit_string_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2647 struct ctf_field_class_string
**string_decl
)
2651 struct ctf_node
*expression
;
2652 enum ctf_encoding encoding
= CTF_ENCODING_UTF8
;
2654 *string_decl
= NULL
;
2656 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2657 struct ctf_node
*left
, *right
;
2659 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2661 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2663 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2664 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2665 left
->u
.unary_expression
.type
);
2670 if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2673 if (_IS_SET(&set
, _STRING_ENCODING_SET
)) {
2674 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "string field class");
2679 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2680 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2681 right
, "Invalid `encoding` attribute in string field class: "
2682 "expecting unary string.");
2687 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2689 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2691 "Unexpected unary expression for string field class's `encoding` attribute.");
2696 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2697 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2698 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2699 encoding
= CTF_ENCODING_UTF8
;
2700 } else if (strcmp(s_right
, "none") == 0) {
2701 encoding
= CTF_ENCODING_NONE
;
2703 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2705 "Invalid `encoding` attribute in string field class: "
2706 "unknown encoding: encoding=\"%s\"",
2714 _SET(&set
, _STRING_ENCODING_SET
);
2716 _BT_COMP_LOGW_NODE(left
,
2717 "Unknown attribute in string field class: "
2719 left
->u
.unary_expression
.u
.string
);
2723 *string_decl
= ctf_field_class_string_create();
2724 BT_ASSERT(*string_decl
);
2725 (*string_decl
)->encoding
= encoding
;
2729 ctf_field_class_destroy(&(*string_decl
)->base
);
2730 *string_decl
= NULL
;
2734 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
2735 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
)
2738 struct ctf_node
*first
, *node
;
2742 if (ts_list
->type
!= NODE_TYPE_SPECIFIER_LIST
) {
2743 _BT_COMP_LOGE_APPEND_CAUSE_NODE(ts_list
, "Unexpected node type: node-type=%d",
2749 first
= _BT_LIST_FIRST_ENTRY(&ts_list
->u
.field_class_specifier_list
.head
, struct ctf_node
,
2751 if (first
->type
!= NODE_TYPE_SPECIFIER
) {
2752 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type=%d", first
->type
);
2757 node
= first
->u
.field_class_specifier
.node
;
2759 switch (first
->u
.field_class_specifier
.type
) {
2760 case TYPESPEC_INTEGER
:
2762 ctf_field_class_int
*int_decl
;
2764 ret
= visit_integer_decl(ctx
, &node
->u
.integer
.expressions
, &int_decl
);
2766 BT_ASSERT(!int_decl
);
2770 *decl
= &int_decl
->base
.base
;
2773 case TYPESPEC_FLOATING_POINT
:
2775 ctf_field_class_float
*float_decl
;
2778 visit_floating_point_number_decl(ctx
, &node
->u
.floating_point
.expressions
, &float_decl
);
2780 BT_ASSERT(!float_decl
);
2784 *decl
= &float_decl
->base
.base
;
2787 case TYPESPEC_STRING
:
2789 ctf_field_class_string
*string_decl
;
2791 ret
= visit_string_decl(ctx
, &node
->u
.string
.expressions
, &string_decl
);
2793 BT_ASSERT(!string_decl
);
2797 *decl
= &string_decl
->base
;
2800 case TYPESPEC_STRUCT
:
2802 ctf_field_class_struct
*struct_decl
;
2804 ret
= visit_struct_decl(ctx
, node
->u
._struct
.name
, &node
->u
._struct
.declaration_list
,
2805 node
->u
._struct
.has_body
, &node
->u
._struct
.min_align
, &struct_decl
);
2807 BT_ASSERT(!struct_decl
);
2811 *decl
= &struct_decl
->base
;
2814 case TYPESPEC_VARIANT
:
2816 ctf_field_class_variant
*variant_decl
;
2818 ret
= visit_variant_decl(ctx
, node
->u
.variant
.name
, node
->u
.variant
.choice
,
2819 &node
->u
.variant
.declaration_list
, node
->u
.variant
.has_body
,
2822 BT_ASSERT(!variant_decl
);
2826 *decl
= &variant_decl
->base
;
2831 ctf_field_class_enum
*enum_decl
;
2833 ret
= visit_enum_decl(ctx
, node
->u
._enum
.enum_id
, node
->u
._enum
.container_field_class
,
2834 &node
->u
._enum
.enumerator_list
, node
->u
._enum
.has_body
, &enum_decl
);
2836 BT_ASSERT(!enum_decl
);
2840 *decl
= &enum_decl
->base
.base
.base
;
2845 case TYPESPEC_SHORT
:
2848 case TYPESPEC_FLOAT
:
2849 case TYPESPEC_DOUBLE
:
2850 case TYPESPEC_SIGNED
:
2851 case TYPESPEC_UNSIGNED
:
2853 case TYPESPEC_COMPLEX
:
2854 case TYPESPEC_IMAGINARY
:
2855 case TYPESPEC_CONST
:
2856 case TYPESPEC_ID_TYPE
:
2857 ret
= visit_field_class_specifier(ctx
, ts_list
, decl
);
2859 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Cannot visit field class specifier: ret=%d",
2866 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
,
2867 "Unexpected field class specifier type: node-type=%d",
2868 first
->u
.field_class_specifier
.type
);
2877 ctf_field_class_destroy(*decl
);
2882 static int visit_event_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
2883 struct ctf_event_class
*event_class
, uint64_t *stream_id
,
2889 switch (node
->type
) {
2891 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
2892 &node
->u
.field_class_def
.field_class_declarators
);
2894 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in event class.");
2898 case NODE_TYPEALIAS
:
2899 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
2900 node
->u
.field_class_alias
.alias
);
2902 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2903 "Cannot add field class alias found in event class.");
2907 case NODE_CTF_EXPRESSION
:
2909 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
2911 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
2916 if (strcmp(left
, "name") == 0) {
2917 /* This is already known at this stage */
2918 if (_IS_SET(set
, _EVENT_NAME_SET
)) {
2919 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "name", "event class");
2924 _SET(set
, _EVENT_NAME_SET
);
2925 } else if (strcmp(left
, "id") == 0) {
2928 if (_IS_SET(set
, _EVENT_ID_SET
)) {
2929 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "event class");
2934 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
2935 /* Only read "id" if get_unary_unsigned() succeeded. */
2936 if (ret
|| (!ret
&& id
< 0)) {
2937 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2938 node
, "Unexpected unary expression for event class's `id` attribute.");
2943 event_class
->id
= id
;
2944 _SET(set
, _EVENT_ID_SET
);
2945 } else if (strcmp(left
, "stream_id") == 0) {
2946 if (_IS_SET(set
, _EVENT_STREAM_ID_SET
)) {
2947 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "stream_id", "event class");
2952 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, stream_id
);
2955 * Only read "stream_id" if get_unary_unsigned()
2959 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2960 node
, "Unexpected unary expression for event class's `stream_id` attribute.");
2965 _SET(set
, _EVENT_STREAM_ID_SET
);
2966 } else if (strcmp(left
, "context") == 0) {
2967 if (_IS_SET(set
, _EVENT_CONTEXT_SET
)) {
2968 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `context` entry in event class.");
2973 ret
= visit_field_class_specifier_list(
2974 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2975 &event_class
->spec_context_fc
);
2977 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2978 "Cannot create event class's context field class.");
2982 BT_ASSERT(event_class
->spec_context_fc
);
2983 _SET(set
, _EVENT_CONTEXT_SET
);
2984 } else if (strcmp(left
, "fields") == 0) {
2985 if (_IS_SET(set
, _EVENT_FIELDS_SET
)) {
2986 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `fields` entry in event class.");
2991 ret
= visit_field_class_specifier_list(
2992 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2993 &event_class
->payload_fc
);
2995 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2996 "Cannot create event class's payload field class.");
3000 BT_ASSERT(event_class
->payload_fc
);
3001 _SET(set
, _EVENT_FIELDS_SET
);
3002 } else if (strcmp(left
, "loglevel") == 0) {
3003 uint64_t loglevel_value
;
3004 bool is_log_level_known
= true;
3005 bt_event_class_log_level log_level
;
3007 if (_IS_SET(set
, _EVENT_LOG_LEVEL_SET
)) {
3008 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "loglevel", "event class");
3013 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &loglevel_value
);
3015 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3016 node
, "Unexpected unary expression for event class's `loglevel` attribute.");
3021 switch (loglevel_value
) {
3023 log_level
= BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
;
3026 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ALERT
;
3029 log_level
= BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
;
3032 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ERROR
;
3035 log_level
= BT_EVENT_CLASS_LOG_LEVEL_WARNING
;
3038 log_level
= BT_EVENT_CLASS_LOG_LEVEL_NOTICE
;
3041 log_level
= BT_EVENT_CLASS_LOG_LEVEL_INFO
;
3044 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
;
3047 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
;
3050 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
;
3053 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
;
3056 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
;
3059 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
;
3062 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
;
3065 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG
;
3068 is_log_level_known
= false;
3071 "Not setting event class's log level because its value is unknown: "
3072 "log-level=%" PRIu64
,
3076 if (is_log_level_known
) {
3077 ctf_event_class_set_log_level(event_class
, log_level
);
3080 _SET(set
, _EVENT_LOG_LEVEL_SET
);
3081 } else if (strcmp(left
, "model.emf.uri") == 0) {
3084 if (_IS_SET(set
, _EVENT_MODEL_EMF_URI_SET
)) {
3085 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "model.emf.uri", "event class");
3090 right
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.right
);
3092 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3094 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3099 if (strlen(right
) == 0) {
3100 _BT_COMP_LOGW_NODE(node
, "Not setting event class's EMF URI because it's empty.");
3102 g_string_assign(event_class
->emf_uri
, right
);
3106 _SET(set
, _EVENT_MODEL_EMF_URI_SET
);
3108 _BT_COMP_LOGW_NODE(node
,
3109 "Unknown attribute in event class: "
3132 static char *get_event_decl_name(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3136 struct ctf_node
*iter
;
3137 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3139 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3140 if (iter
->type
!= NODE_CTF_EXPRESSION
) {
3144 left
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.left
);
3146 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot concatenate unary strings.");
3150 if (strcmp(left
, "name") == 0) {
3151 name
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.right
);
3153 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3154 iter
, "Unexpected unary expression for event class's `name` attribute.");
3174 static int visit_event_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3178 struct ctf_node
*iter
;
3179 uint64_t stream_id
= 0;
3180 char *event_name
= NULL
;
3181 struct ctf_event_class
*event_class
= NULL
;
3182 struct ctf_stream_class
*stream_class
= NULL
;
3183 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3184 bool pop_scope
= false;
3186 if (node
->visited
) {
3190 node
->visited
= TRUE
;
3191 event_name
= get_event_decl_name(ctx
, node
);
3193 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `name` attribute in event class.");
3198 event_class
= ctf_event_class_create();
3199 BT_ASSERT(event_class
);
3200 g_string_assign(event_class
->name
, event_name
);
3201 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3204 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3205 ret
= visit_event_decl_entry(ctx
, iter
, event_class
, &stream_id
, &set
);
3207 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3208 "Cannot visit event class's entry: "
3215 if (!_IS_SET(&set
, _EVENT_STREAM_ID_SET
)) {
3217 * Allow missing stream_id if there is only a single
3220 switch (ctx
->ctf_tc
->stream_classes
->len
) {
3222 /* Create implicit stream class if there's none */
3224 stream_class
= ctf_stream_class_create();
3225 BT_ASSERT(stream_class
);
3226 stream_class
->id
= stream_id
;
3227 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3230 /* Single stream class: get its ID */
3231 stream_class
= (ctf_stream_class
*) ctx
->ctf_tc
->stream_classes
->pdata
[0];
3232 stream_id
= stream_class
->id
;
3235 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `stream_id` attribute in event class.");
3241 /* We have the stream ID now; get the stream class if found */
3242 if (!stream_class
) {
3243 stream_class
= ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_id
);
3244 if (!stream_class
) {
3245 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3246 "Cannot find stream class at this point: "
3254 BT_ASSERT(stream_class
);
3256 if (!_IS_SET(&set
, _EVENT_ID_SET
)) {
3257 /* Allow only one event without ID per stream */
3258 if (stream_class
->event_classes
->len
!= 0) {
3259 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `id` attribute in event class.");
3265 event_class
->id
= 0;
3268 if (ctf_stream_class_borrow_event_class_by_id(stream_class
, event_class
->id
)) {
3269 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3270 "Duplicate event class (same ID) in the same stream class: "
3277 ctf_stream_class_append_event_class(stream_class
, event_class
);
3282 ctf_event_class_destroy(event_class
);
3299 static int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3300 struct ctf_field_class
*fc
)
3302 struct ctf_clock_class
*clock_class_to_map_to
= NULL
;
3303 struct ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
3305 uint64_t clock_class_count
;
3311 if (fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&& fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3315 if (int_fc
->mapped_clock_class
) {
3316 /* Already mapped */
3320 clock_class_count
= ctx
->ctf_tc
->clock_classes
->len
;
3322 switch (clock_class_count
) {
3325 * No clock class exists in the trace at this point. Create an
3326 * implicit one at 1 GHz, named `default`, and use this clock
3329 clock_class_to_map_to
= ctf_clock_class_create();
3330 BT_ASSERT(clock_class_to_map_to
);
3331 clock_class_to_map_to
->frequency
= UINT64_C(1000000000);
3332 g_string_assign(clock_class_to_map_to
->name
, "default");
3333 BT_ASSERT(ret
== 0);
3334 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock_class_to_map_to
);
3338 * Only one clock class exists in the trace at this point: use
3341 clock_class_to_map_to
= (ctf_clock_class
*) ctx
->ctf_tc
->clock_classes
->pdata
[0];
3345 * Timestamp field not mapped to a clock class and there's more
3346 * than one clock class in the trace: this is an error.
3348 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3349 "Timestamp field found with no mapped clock class, "
3350 "but there's more than one clock class in the trace at this point.");
3355 BT_ASSERT(clock_class_to_map_to
);
3356 int_fc
->mapped_clock_class
= clock_class_to_map_to
;
3362 static int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3363 struct ctf_field_class
*root_fc
,
3364 const char *field_name
)
3368 struct ctf_field_class_struct
*struct_fc
= (ctf_field_class_struct
*) root_fc
;
3369 struct ctf_field_class_variant
*var_fc
= (ctf_field_class_variant
*) root_fc
;
3375 if (root_fc
->type
!= CTF_FIELD_CLASS_TYPE_STRUCT
&&
3376 root_fc
->type
!= CTF_FIELD_CLASS_TYPE_VARIANT
) {
3380 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3381 count
= struct_fc
->members
->len
;
3383 count
= var_fc
->options
->len
;
3386 for (i
= 0; i
< count
; i
++) {
3387 struct ctf_named_field_class
*named_fc
= NULL
;
3389 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3390 named_fc
= ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
3391 } else if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
3392 named_fc
= ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
3397 if (strcmp(named_fc
->name
->str
, field_name
) == 0) {
3398 ret
= auto_map_field_to_trace_clock_class(ctx
, named_fc
->fc
);
3400 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3401 "Cannot automatically map field to trace's clock class: "
3402 "field-name=\"%s\"",
3408 ret
= auto_map_fields_to_trace_clock_class(ctx
, named_fc
->fc
, field_name
);
3410 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3411 "Cannot automatically map structure or variant field class's fields to trace's clock class: "
3412 "field-name=\"%s\", root-field-name=\"%s\"",
3413 field_name
, named_fc
->name
->str
);
3422 static int visit_stream_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3423 struct ctf_stream_class
*stream_class
, int *set
)
3428 switch (node
->type
) {
3430 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3431 &node
->u
.field_class_def
.field_class_declarators
);
3433 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in stream class.");
3437 case NODE_TYPEALIAS
:
3438 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3439 node
->u
.field_class_alias
.alias
);
3441 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3442 "Cannot add field class alias found in stream class.");
3446 case NODE_CTF_EXPRESSION
:
3448 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3450 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3455 if (strcmp(left
, "id") == 0) {
3458 if (_IS_SET(set
, _STREAM_ID_SET
)) {
3459 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "stream declaration");
3464 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
3466 /* Only read "id" if get_unary_unsigned() succeeded. */
3467 if (ret
|| (!ret
&& id
< 0)) {
3468 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3469 node
, "Unexpected unary expression for stream class's `id` attribute.");
3474 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, id
)) {
3475 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3476 node
, "Duplicate stream class (same ID): id=%" PRId64
, id
);
3481 stream_class
->id
= id
;
3482 _SET(set
, _STREAM_ID_SET
);
3483 } else if (strcmp(left
, "event.header") == 0) {
3484 if (_IS_SET(set
, _STREAM_EVENT_HEADER_SET
)) {
3485 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3486 "Duplicate `event.header` entry in stream class.");
3491 ret
= visit_field_class_specifier_list(
3492 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3493 &stream_class
->event_header_fc
);
3495 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3496 node
, "Cannot create stream class's event header field class.");
3500 BT_ASSERT(stream_class
->event_header_fc
);
3501 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->event_header_fc
,
3504 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3506 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3510 _SET(set
, _STREAM_EVENT_HEADER_SET
);
3511 } else if (strcmp(left
, "event.context") == 0) {
3512 if (_IS_SET(set
, _STREAM_EVENT_CONTEXT_SET
)) {
3513 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3514 "Duplicate `event.context` entry in stream class.");
3519 ret
= visit_field_class_specifier_list(
3520 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3521 &stream_class
->event_common_context_fc
);
3523 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3524 node
, "Cannot create stream class's event context field class.");
3528 BT_ASSERT(stream_class
->event_common_context_fc
);
3529 _SET(set
, _STREAM_EVENT_CONTEXT_SET
);
3530 } else if (strcmp(left
, "packet.context") == 0) {
3531 if (_IS_SET(set
, _STREAM_PACKET_CONTEXT_SET
)) {
3532 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3533 node
, "Duplicate `packet.context` entry in stream class.");
3538 ret
= visit_field_class_specifier_list(
3539 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3540 &stream_class
->packet_context_fc
);
3542 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3543 node
, "Cannot create stream class's packet context field class.");
3547 BT_ASSERT(stream_class
->packet_context_fc
);
3548 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3551 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3553 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3557 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3560 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3562 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3566 _SET(set
, _STREAM_PACKET_CONTEXT_SET
);
3568 _BT_COMP_LOGW_NODE(node
,
3569 "Unknown attribute in stream class: "
3591 static int visit_stream_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3595 struct ctf_node
*iter
;
3596 struct ctf_stream_class
*stream_class
= NULL
;
3597 struct bt_list_head
*decl_list
= &node
->u
.stream
.declaration_list
;
3599 if (node
->visited
) {
3603 node
->visited
= TRUE
;
3604 stream_class
= ctf_stream_class_create();
3605 BT_ASSERT(stream_class
);
3606 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3608 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3609 ret
= visit_stream_decl_entry(ctx
, iter
, stream_class
, &set
);
3611 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3612 "Cannot visit stream class's entry: "
3622 if (_IS_SET(&set
, _STREAM_ID_SET
)) {
3623 /* Check that packet header has `stream_id` field */
3624 struct ctf_named_field_class
*named_fc
= NULL
;
3626 if (!ctx
->ctf_tc
->packet_header_fc
) {
3627 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Stream class has a `id` attribute, "
3628 "but trace has no packet header field class.");
3633 named_fc
= ctf_field_class_struct_borrow_member_by_name(
3634 ctf_field_class_as_struct(ctx
->ctf_tc
->packet_header_fc
), "stream_id");
3636 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3637 node
, "Stream class has a `id` attribute, "
3638 "but trace's packet header field class has no `stream_id` field.");
3643 if (named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3644 named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3645 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3647 "Stream class has a `id` attribute, "
3648 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3653 /* Allow only _one_ ID-less stream */
3654 if (ctx
->ctf_tc
->stream_classes
->len
!= 0) {
3655 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3657 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3662 /* Automatic ID: 0 */
3663 stream_class
->id
= 0;
3667 * Make sure that this stream class's ID is currently unique in
3670 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_class
->id
)) {
3671 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate stream class (same ID): id=%" PRId64
,
3677 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3678 stream_class
= NULL
;
3682 ctf_stream_class_destroy(stream_class
);
3683 stream_class
= NULL
;
3689 static int visit_trace_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3696 switch (node
->type
) {
3698 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3699 &node
->u
.field_class_def
.field_class_declarators
);
3701 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3702 node
, "Cannot add field class found in trace (`trace` block).");
3706 case NODE_TYPEALIAS
:
3707 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3708 node
->u
.field_class_alias
.alias
);
3710 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3711 node
, "Cannot add field class alias found in trace (`trace` block).");
3715 case NODE_CTF_EXPRESSION
:
3717 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3719 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3724 if (strcmp(left
, "major") == 0) {
3725 if (_IS_SET(set
, _TRACE_MAJOR_SET
)) {
3726 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "major", "trace");
3731 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3733 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3734 node
, "Unexpected unary expression for trace's `major` attribute.");
3740 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3741 "Invalid trace's `minor` attribute: expecting 1.");
3746 ctx
->ctf_tc
->major
= val
;
3747 _SET(set
, _TRACE_MAJOR_SET
);
3748 } else if (strcmp(left
, "minor") == 0) {
3749 if (_IS_SET(set
, _TRACE_MINOR_SET
)) {
3750 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "minor", "trace");
3755 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3757 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3758 node
, "Unexpected unary expression for trace's `minor` attribute.");
3764 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3765 "Invalid trace's `minor` attribute: expecting 8.");
3770 ctx
->ctf_tc
->minor
= val
;
3771 _SET(set
, _TRACE_MINOR_SET
);
3772 } else if (strcmp(left
, "uuid") == 0) {
3773 if (_IS_SET(set
, _TRACE_UUID_SET
)) {
3774 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "uuid", "trace");
3779 ret
= get_unary_uuid(ctx
, &node
->u
.ctf_expression
.right
, ctx
->ctf_tc
->uuid
);
3781 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid trace's `uuid` attribute.");
3785 ctx
->ctf_tc
->is_uuid_set
= true;
3786 _SET(set
, _TRACE_UUID_SET
);
3787 } else if (strcmp(left
, "byte_order") == 0) {
3788 /* Default byte order is already known at this stage */
3789 if (_IS_SET(set
, _TRACE_BYTE_ORDER_SET
)) {
3790 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
3795 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
!= CTF_BYTE_ORDER_UNKNOWN
);
3796 _SET(set
, _TRACE_BYTE_ORDER_SET
);
3797 } else if (strcmp(left
, "packet.header") == 0) {
3798 if (_IS_SET(set
, _TRACE_PACKET_HEADER_SET
)) {
3799 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `packet.header` entry in trace.");
3804 ret
= visit_field_class_specifier_list(
3805 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3806 &ctx
->ctf_tc
->packet_header_fc
);
3808 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3809 "Cannot create trace's packet header field class.");
3813 BT_ASSERT(ctx
->ctf_tc
->packet_header_fc
);
3814 _SET(set
, _TRACE_PACKET_HEADER_SET
);
3816 _BT_COMP_LOGW_NODE(node
,
3817 "Unknown attribute in stream class: "
3827 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unknown expression in trace.");
3839 static int visit_trace_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3843 struct ctf_node
*iter
;
3844 struct bt_list_head
*decl_list
= &node
->u
.trace
.declaration_list
;
3846 if (node
->visited
) {
3850 node
->visited
= TRUE
;
3852 if (ctx
->is_trace_visited
) {
3853 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
3858 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3860 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3861 ret
= visit_trace_decl_entry(ctx
, iter
, &set
);
3863 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3864 "Cannot visit trace's entry (`trace` block): "
3874 if (!_IS_SET(&set
, _TRACE_MAJOR_SET
)) {
3875 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3876 "Missing `major` attribute in trace (`trace` block).");
3881 if (!_IS_SET(&set
, _TRACE_MINOR_SET
)) {
3882 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3883 "Missing `minor` attribute in trace (`trace` block).");
3888 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3889 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3890 "Missing `byte_order` attribute in trace (`trace` block).");
3895 ctx
->is_trace_visited
= true;
3904 static int visit_env(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3908 struct ctf_node
*entry_node
;
3909 struct bt_list_head
*decl_list
= &node
->u
.env
.declaration_list
;
3911 if (node
->visited
) {
3915 node
->visited
= TRUE
;
3917 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
3918 struct bt_list_head
*right_head
= &entry_node
->u
.ctf_expression
.right
;
3920 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
3921 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
3922 "Wrong expression in environment entry: "
3929 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
3931 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot get environment entry's name.");
3936 if (is_unary_string(right_head
)) {
3937 char *right
= ctf_ast_concatenate_unary_strings(right_head
);
3940 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3942 "Unexpected unary expression for environment entry's value: "
3949 if (strcmp(left
, "tracer_name") == 0) {
3950 if (strncmp(right
, "lttng", 5) == 0) {
3951 BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: "
3952 "tracer-name=\"%s\"",
3954 ctx
->is_lttng
= true;
3958 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
,
3961 } else if (is_unary_unsigned(right_head
) || is_unary_signed(right_head
)) {
3964 if (is_unary_unsigned(right_head
)) {
3965 ret
= get_unary_unsigned(ctx
, right_head
, (uint64_t *) &v
);
3967 ret
= get_unary_signed(right_head
, &v
);
3970 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3972 "Unexpected unary expression for environment entry's value: "
3979 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
,
3982 _BT_COMP_LOGW_NODE(entry_node
,
3983 "Environment entry has unknown type: "
4000 static int set_trace_byte_order(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*trace_node
)
4005 struct ctf_node
*node
;
4006 struct bt_list_head
*decl_list
= &trace_node
->u
.trace
.declaration_list
;
4008 bt_list_for_each_entry (node
, decl_list
, siblings
) {
4009 if (node
->type
== NODE_CTF_EXPRESSION
) {
4010 struct ctf_node
*right_node
;
4012 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
4014 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
4019 if (strcmp(left
, "byte_order") == 0) {
4020 enum ctf_byte_order bo
;
4022 if (_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4023 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
4028 _SET(&set
, _TRACE_BYTE_ORDER_SET
);
4030 _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4031 bo
= byte_order_from_unary_expr(ctx
, right_node
);
4032 if (bo
== CTF_BYTE_ORDER_UNKNOWN
) {
4033 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4034 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4035 "expecting `le`, `be`, or `network`.");
4038 } else if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
4039 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4040 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4041 "cannot be set to `native` here.");
4046 ctx
->ctf_tc
->default_byte_order
= bo
;
4054 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4055 _BT_COMP_LOGE_APPEND_CAUSE_NODE(trace_node
,
4056 "Missing `byte_order` attribute in trace (`trace` block).");
4068 static int visit_clock_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
4069 struct ctf_clock_class
*clock
, int *set
, int64_t *offset_seconds
,
4070 uint64_t *offset_cycles
)
4075 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4076 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
4082 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
4084 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot concatenate unary strings.");
4089 if (strcmp(left
, "name") == 0) {
4092 if (_IS_SET(set
, _CLOCK_NAME_SET
)) {
4093 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "name", "clock class");
4098 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4100 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4101 entry_node
, "Unexpected unary expression for clock class's `name` attribute.");
4106 g_string_assign(clock
->name
, right
);
4108 _SET(set
, _CLOCK_NAME_SET
);
4109 } else if (strcmp(left
, "uuid") == 0) {
4112 if (_IS_SET(set
, _CLOCK_UUID_SET
)) {
4113 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "uuid", "clock class");
4118 ret
= get_unary_uuid(ctx
, &entry_node
->u
.ctf_expression
.right
, uuid
);
4120 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Invalid clock class's `uuid` attribute.");
4124 clock
->has_uuid
= true;
4125 bt_uuid_copy(clock
->uuid
, uuid
);
4126 _SET(set
, _CLOCK_UUID_SET
);
4127 } else if (strcmp(left
, "description") == 0) {
4130 if (_IS_SET(set
, _CLOCK_DESCRIPTION_SET
)) {
4131 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "description", "clock class");
4136 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4138 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4140 "Unexpected unary expression for clock class's `description` attribute.");
4145 g_string_assign(clock
->description
, right
);
4147 _SET(set
, _CLOCK_DESCRIPTION_SET
);
4148 } else if (strcmp(left
, "freq") == 0) {
4149 uint64_t freq
= UINT64_C(-1);
4151 if (_IS_SET(set
, _CLOCK_FREQ_SET
)) {
4152 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "freq", "clock class");
4157 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &freq
);
4159 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4160 entry_node
, "Unexpected unary expression for clock class's `freq` attribute.");
4165 if (freq
== UINT64_C(-1) || freq
== 0) {
4166 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4167 "Invalid clock class frequency: freq=%" PRIu64
, freq
);
4172 clock
->frequency
= freq
;
4173 _SET(set
, _CLOCK_FREQ_SET
);
4174 } else if (strcmp(left
, "precision") == 0) {
4177 if (_IS_SET(set
, _CLOCK_PRECISION_SET
)) {
4178 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "precision", "clock class");
4183 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &precision
);
4185 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4186 entry_node
, "Unexpected unary expression for clock class's `precision` attribute.");
4191 clock
->precision
= precision
;
4192 _SET(set
, _CLOCK_PRECISION_SET
);
4193 } else if (strcmp(left
, "offset_s") == 0) {
4194 if (_IS_SET(set
, _CLOCK_OFFSET_S_SET
)) {
4195 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset_s", "clock class");
4200 ret
= get_unary_signed(&entry_node
->u
.ctf_expression
.right
, offset_seconds
);
4202 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4203 entry_node
, "Unexpected unary expression for clock class's `offset_s` attribute.");
4208 _SET(set
, _CLOCK_OFFSET_S_SET
);
4209 } else if (strcmp(left
, "offset") == 0) {
4210 if (_IS_SET(set
, _CLOCK_OFFSET_SET
)) {
4211 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset", "clock class");
4216 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, offset_cycles
);
4218 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4219 entry_node
, "Unexpected unary expression for clock class's `offset` attribute.");
4224 _SET(set
, _CLOCK_OFFSET_SET
);
4225 } else if (strcmp(left
, "absolute") == 0) {
4226 struct ctf_node
*right
;
4228 if (_IS_SET(set
, _CLOCK_ABSOLUTE_SET
)) {
4229 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "absolute", "clock class");
4235 _BT_LIST_FIRST_ENTRY(&entry_node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4236 ret
= get_boolean(ctx
, right
);
4238 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4239 entry_node
, "Unexpected unary expression for clock class's `absolute` attribute.");
4244 clock
->is_absolute
= ret
;
4245 _SET(set
, _CLOCK_ABSOLUTE_SET
);
4247 _BT_COMP_LOGW_NODE(entry_node
, "Unknown attribute in clock class: attr-name=\"%s\"", left
);
4259 static inline uint64_t cycles_from_ns(uint64_t frequency
, uint64_t ns
)
4264 if (frequency
== UINT64_C(1000000000)) {
4267 cycles
= (uint64_t) (((double) ns
* (double) frequency
) / 1e9
);
4273 static void calibrate_clock_class_offsets(int64_t *offset_seconds
, uint64_t *offset_cycles
,
4276 if (*offset_cycles
>= freq
) {
4277 const uint64_t s_in_offset_cycles
= *offset_cycles
/ freq
;
4279 *offset_seconds
+= (int64_t) s_in_offset_cycles
;
4280 *offset_cycles
-= (s_in_offset_cycles
* freq
);
4284 static void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir
*ctx
,
4285 struct ctf_clock_class
*clock
)
4287 if (ctx
->decoder_config
.force_clock_class_origin_unix_epoch
) {
4288 clock
->is_absolute
= true;
4294 static void apply_clock_class_offset(struct ctf_visitor_generate_ir
*ctx
,
4295 struct ctf_clock_class
*clock
)
4298 int64_t offset_s_to_apply
= ctx
->decoder_config
.clock_class_offset_s
;
4299 uint64_t offset_ns_to_apply
;
4300 int64_t cur_offset_s
;
4301 uint64_t cur_offset_cycles
;
4303 if (ctx
->decoder_config
.clock_class_offset_s
== 0 &&
4304 ctx
->decoder_config
.clock_class_offset_ns
== 0) {
4308 /* Transfer nanoseconds to seconds as much as possible */
4309 if (ctx
->decoder_config
.clock_class_offset_ns
< 0) {
4310 const int64_t abs_ns
= -ctx
->decoder_config
.clock_class_offset_ns
;
4311 const int64_t abs_extra_s
= abs_ns
/ INT64_C(1000000000) + 1;
4312 const int64_t extra_s
= -abs_extra_s
;
4313 const int64_t offset_ns
=
4314 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4316 BT_ASSERT(offset_ns
> 0);
4317 offset_ns_to_apply
= (uint64_t) offset_ns
;
4318 offset_s_to_apply
+= extra_s
;
4320 const int64_t extra_s
= ctx
->decoder_config
.clock_class_offset_ns
/ INT64_C(1000000000);
4321 const int64_t offset_ns
=
4322 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4324 BT_ASSERT(offset_ns
>= 0);
4325 offset_ns_to_apply
= (uint64_t) offset_ns
;
4326 offset_s_to_apply
+= extra_s
;
4329 freq
= clock
->frequency
;
4330 cur_offset_s
= clock
->offset_seconds
;
4331 cur_offset_cycles
= clock
->offset_cycles
;
4334 cur_offset_s
+= offset_s_to_apply
;
4335 cur_offset_cycles
+= cycles_from_ns(freq
, offset_ns_to_apply
);
4338 * Recalibrate offsets because the part in cycles can be greater
4339 * than the frequency at this point.
4341 calibrate_clock_class_offsets(&cur_offset_s
, &cur_offset_cycles
, freq
);
4343 /* Set final offsets */
4344 clock
->offset_seconds
= cur_offset_s
;
4345 clock
->offset_cycles
= cur_offset_cycles
;
4351 static int visit_clock_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*clock_node
)
4355 struct ctf_clock_class
*clock
;
4356 struct ctf_node
*entry_node
;
4357 struct bt_list_head
*decl_list
= &clock_node
->u
.clock
.declaration_list
;
4358 const char *clock_class_name
;
4359 int64_t offset_seconds
= 0;
4360 uint64_t offset_cycles
= 0;
4363 if (clock_node
->visited
) {
4367 clock_node
->visited
= TRUE
;
4369 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4370 clock
= ctf_clock_class_create();
4372 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
, "Cannot create default clock class.");
4377 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
4378 ret
= visit_clock_decl_entry(ctx
, entry_node
, clock
, &set
, &offset_seconds
, &offset_cycles
);
4380 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot visit clock class's entry: ret=%d",
4386 if (!_IS_SET(&set
, _CLOCK_NAME_SET
)) {
4387 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
, "Missing `name` attribute in clock class.");
4392 clock_class_name
= clock
->name
->str
;
4393 BT_ASSERT(clock_class_name
);
4394 if (ctx
->is_lttng
&& strcmp(clock_class_name
, "monotonic") == 0) {
4396 * Old versions of LTTng forgot to set its clock class
4397 * as absolute, even if it is. This is important because
4398 * it's a condition to be able to sort messages
4399 * from different sources.
4401 clock
->is_absolute
= true;
4405 * Adjust offsets so that the part in cycles is less than the
4406 * frequency (move to the part in seconds).
4408 freq
= clock
->frequency
;
4409 calibrate_clock_class_offsets(&offset_seconds
, &offset_cycles
, freq
);
4410 BT_ASSERT(offset_cycles
< clock
->frequency
);
4411 clock
->offset_seconds
= offset_seconds
;
4412 clock
->offset_cycles
= offset_cycles
;
4413 apply_clock_class_offset(ctx
, clock
);
4414 apply_clock_class_is_absolute(ctx
, clock
);
4415 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock
);
4420 ctf_clock_class_destroy(clock
);
4426 static int visit_root_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*root_decl_node
)
4430 if (root_decl_node
->visited
) {
4434 root_decl_node
->visited
= TRUE
;
4436 switch (root_decl_node
->type
) {
4439 visit_field_class_def(ctx
, root_decl_node
->u
.field_class_def
.field_class_specifier_list
,
4440 &root_decl_node
->u
.field_class_def
.field_class_declarators
);
4442 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4443 "Cannot add field class found in root scope.");
4447 case NODE_TYPEALIAS
:
4448 ret
= visit_field_class_alias(ctx
, root_decl_node
->u
.field_class_alias
.target
,
4449 root_decl_node
->u
.field_class_alias
.alias
);
4451 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4452 "Cannot add field class alias found in root scope.");
4456 case NODE_TYPE_SPECIFIER_LIST
:
4458 struct ctf_field_class
*decl
= NULL
;
4461 * Just add the field class specifier to the root
4462 * declaration scope. Put local reference.
4464 ret
= visit_field_class_specifier_list(ctx
, root_decl_node
, &decl
);
4466 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4467 "Cannot visit root scope's field class: "
4474 ctf_field_class_destroy(decl
);
4479 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
, "Unexpected node type: node-type=%d",
4480 root_decl_node
->type
);
4490 struct ctf_visitor_generate_ir
*
4491 ctf_visitor_generate_ir_create(const struct ctf_metadata_decoder_config
*decoder_config
)
4493 struct ctf_visitor_generate_ir
*ctx
= NULL
;
4495 /* Create visitor's context */
4496 ctx
= ctx_create(decoder_config
);
4498 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
, decoder_config
->self_comp
,
4499 "Cannot create visitor's context.");
4514 void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir
*visitor
)
4516 ctx_destroy(visitor
);
4520 bt_trace_class
*ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4524 if (ctx
->trace_class
) {
4525 bt_trace_class_get_ref(ctx
->trace_class
);
4528 return ctx
->trace_class
;
4532 struct ctf_trace_class
*
4533 ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4536 BT_ASSERT_DBG(ctx
->ctf_tc
);
4541 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
4545 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
4547 switch (node
->type
) {
4550 struct ctf_node
*iter
;
4551 bool got_trace_decl
= false;
4554 * The first thing we need is the native byte order of
4555 * the trace block, because early class aliases can have
4556 * a `byte_order` attribute set to `native`. If we don't
4557 * have the native byte order yet, and we don't have any
4558 * trace block yet, then fail with EINCOMPLETE.
4560 if (ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
4561 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4562 if (got_trace_decl
) {
4563 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
4568 ret
= set_trace_byte_order(ctx
, iter
);
4570 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4571 "Cannot set trace's native byte order: "
4577 got_trace_decl
= true;
4580 if (!got_trace_decl
) {
4581 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
4587 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_LITTLE
||
4588 ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_BIG
);
4589 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4592 bt_list_for_each_entry (iter
, &node
->u
.root
.env
, siblings
) {
4593 ret
= visit_env(ctx
, iter
);
4595 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4597 "Cannot visit trace's environment (`env` block) entry: "
4604 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4607 * Visit clock blocks.
4609 bt_list_for_each_entry (iter
, &node
->u
.root
.clock
, siblings
) {
4610 ret
= visit_clock_decl(ctx
, iter
);
4612 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit clock class: ret=%d", ret
);
4617 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4620 * Visit root declarations next, as they can be used by any
4623 bt_list_for_each_entry (iter
, &node
->u
.root
.declaration_list
, siblings
) {
4624 ret
= visit_root_decl(ctx
, iter
);
4626 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit root entry: ret=%d", ret
);
4631 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4633 /* Callsite blocks are not supported */
4634 bt_list_for_each_entry (iter
, &node
->u
.root
.callsite
, siblings
) {
4635 _BT_COMP_LOGW_NODE(iter
, "\"callsite\" blocks are not supported as of this version.");
4638 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4641 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4642 ret
= visit_trace_decl(ctx
, iter
);
4644 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4645 "Cannot visit trace (`trace` block): "
4652 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4655 bt_list_for_each_entry (iter
, &node
->u
.root
.stream
, siblings
) {
4656 ret
= visit_stream_decl(ctx
, iter
);
4658 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit stream class: ret=%d", ret
);
4663 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4666 bt_list_for_each_entry (iter
, &node
->u
.root
.event
, siblings
) {
4667 ret
= visit_event_decl(ctx
, iter
);
4669 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit event class: ret=%d", ret
);
4674 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4678 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected node type: node-type=%d", node
->type
);
4683 /* Update default clock classes */
4684 ret
= ctf_trace_class_update_default_clock_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4690 /* Update trace class meanings */
4691 ret
= ctf_trace_class_update_meanings(ctx
->ctf_tc
);
4697 /* Update stream class configuration */
4698 ret
= ctf_trace_class_update_stream_class_config(ctx
->ctf_tc
);
4704 /* Update text arrays and sequences */
4705 ret
= ctf_trace_class_update_text_array_sequence(ctx
->ctf_tc
);
4711 /* Update structure/array/sequence alignments */
4712 ret
= ctf_trace_class_update_alignments(ctx
->ctf_tc
);
4718 /* Resolve sequence lengths and variant tags */
4719 ret
= ctf_trace_class_resolve_field_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4725 if (ctx
->trace_class
) {
4727 * Update "in IR" for field classes.
4729 * If we have no IR trace class, then we'll have no way
4730 * to create IR fields anyway, so we leave all the
4731 * `in_ir` members false.
4733 ret
= ctf_trace_class_update_in_ir(ctx
->ctf_tc
);
4740 /* Update saved value indexes */
4741 ret
= ctf_trace_class_update_value_storing_indexes(ctx
->ctf_tc
);
4747 /* Validate what we have so far */
4748 ret
= ctf_trace_class_validate(ctx
->ctf_tc
, &ctx
->log_cfg
);
4755 * If there are fields which are not related to the CTF format
4756 * itself in the packet header and in event header field
4757 * classes, warn about it because they are never translated.
4759 ctf_trace_class_warn_meaningless_header_fields(ctx
->ctf_tc
, &ctx
->log_cfg
);
4761 if (ctx
->trace_class
) {
4762 /* Copy new CTF metadata -> new IR metadata */
4763 ret
= ctf_trace_class_translate(ctx
->log_cfg
.self_comp
, ctx
->trace_class
, ctx
->ctf_tc
);