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).
21 #include <babeltrace2/babeltrace.h>
23 #define BT_COMP_LOG_SELF_COMP (ctx->log_cfg.self_comp)
24 #define BT_COMP_LOG_SELF_COMP_CLASS (ctx->log_cfg.self_comp_class)
25 #define BT_LOG_OUTPUT_LEVEL (ctx->log_cfg.log_level)
26 #define BT_LOG_TAG "PLUGIN/CTF/META/IR-VISITOR"
27 #include "logging.hpp"
28 #include "logging/comp-logging.h"
30 #include "common/assert.h"
31 #include "common/common.h"
32 #include "common/uuid.h"
33 #include "compat/endian.h"
36 #include "ctf-meta-visitors.hpp"
37 #include "ctf-meta.hpp"
38 #include "decoder.hpp"
39 #include "scanner.hpp"
41 /* Bit value (left shift) */
42 #define _BV(_val) (1 << (_val))
44 /* Bit is set in a set of bits */
45 #define _IS_SET(_set, _mask) (*(_set) & (_mask))
47 /* Set bit in a set of bits */
48 #define _SET(_set, _mask) (*(_set) |= (_mask))
50 /* Try to push scope, or go to the `error` label */
51 #define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
53 ret = ctx_push_scope(ctx); \
55 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot push scope."); \
60 /* Bits for verifying existing attributes in various declarations */
63 _CLOCK_NAME_SET
= _BV(0),
64 _CLOCK_UUID_SET
= _BV(1),
65 _CLOCK_FREQ_SET
= _BV(2),
66 _CLOCK_PRECISION_SET
= _BV(3),
67 _CLOCK_OFFSET_S_SET
= _BV(4),
68 _CLOCK_OFFSET_SET
= _BV(5),
69 _CLOCK_ABSOLUTE_SET
= _BV(6),
70 _CLOCK_DESCRIPTION_SET
= _BV(7),
75 _INTEGER_ALIGN_SET
= _BV(0),
76 _INTEGER_SIZE_SET
= _BV(1),
77 _INTEGER_BASE_SET
= _BV(2),
78 _INTEGER_ENCODING_SET
= _BV(3),
79 _INTEGER_BYTE_ORDER_SET
= _BV(4),
80 _INTEGER_SIGNED_SET
= _BV(5),
81 _INTEGER_MAP_SET
= _BV(6),
86 _FLOAT_ALIGN_SET
= _BV(0),
87 _FLOAT_MANT_DIG_SET
= _BV(1),
88 _FLOAT_EXP_DIG_SET
= _BV(2),
89 _FLOAT_BYTE_ORDER_SET
= _BV(3),
94 _STRING_ENCODING_SET
= _BV(0),
99 _TRACE_MINOR_SET
= _BV(0),
100 _TRACE_MAJOR_SET
= _BV(1),
101 _TRACE_BYTE_ORDER_SET
= _BV(2),
102 _TRACE_UUID_SET
= _BV(3),
103 _TRACE_PACKET_HEADER_SET
= _BV(4),
108 _STREAM_ID_SET
= _BV(0),
109 _STREAM_PACKET_CONTEXT_SET
= _BV(1),
110 _STREAM_EVENT_HEADER_SET
= _BV(2),
111 _STREAM_EVENT_CONTEXT_SET
= _BV(3),
116 _EVENT_NAME_SET
= _BV(0),
117 _EVENT_ID_SET
= _BV(1),
118 _EVENT_MODEL_EMF_URI_SET
= _BV(2),
119 _EVENT_STREAM_ID_SET
= _BV(3),
120 _EVENT_LOG_LEVEL_SET
= _BV(4),
121 _EVENT_CONTEXT_SET
= _BV(5),
122 _EVENT_FIELDS_SET
= _BV(6),
131 LOG_LEVEL_WARNING
= 4,
132 LOG_LEVEL_NOTICE
= 5,
134 LOG_LEVEL_DEBUG_SYSTEM
= 7,
135 LOG_LEVEL_DEBUG_PROGRAM
= 8,
136 LOG_LEVEL_DEBUG_PROCESS
= 9,
137 LOG_LEVEL_DEBUG_MODULE
= 10,
138 LOG_LEVEL_DEBUG_UNIT
= 11,
139 LOG_LEVEL_DEBUG_FUNCTION
= 12,
140 LOG_LEVEL_DEBUG_LINE
= 13,
141 LOG_LEVEL_DEBUG
= 14,
145 /* Prefixes of class aliases */
146 #define _PREFIX_ALIAS 'a'
147 #define _PREFIX_ENUM 'e'
148 #define _PREFIX_STRUCT 's'
149 #define _PREFIX_VARIANT 'v'
151 /* First entry in a BT list */
152 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) bt_list_entry((_ptr)->next, _class, _member)
154 #define _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \
155 _BT_COMP_LOGE_APPEND_CAUSE_LINENO( \
156 (_node)->lineno, "Duplicate attribute in %s: attr-name=\"%s\"", _entity, _attr)
158 #define _BT_COMP_LOGE_NODE(_node, _msg, args...) _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ##args)
160 #define _BT_COMP_LOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
161 _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, _msg, ##args)
163 #define _BT_COMP_LOGW_NODE(_node, _msg, args...) _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ##args)
165 #define _BT_COMP_LOGT_NODE(_node, _msg, args...) _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ##args)
168 * Declaration scope of a visitor context. This represents a TSDL
169 * lexical scope, so that aliases and named structures, variants,
170 * and enumerations may be registered and looked up hierarchically.
172 struct ctx_decl_scope
175 * Alias name to field class.
177 * GQuark -> struct ctf_field_class * (owned by this)
179 GHashTable
*decl_map
;
181 /* Parent scope; NULL if this is the root declaration scope */
182 struct ctx_decl_scope
*parent_scope
;
186 * Visitor context (private).
188 struct ctf_visitor_generate_ir
190 struct meta_log_config log_cfg
;
192 /* Trace IR trace class being filled (owned by this) */
193 bt_trace_class
*trace_class
;
195 /* CTF meta trace being filled (owned by this) */
196 struct ctf_trace_class
*ctf_tc
;
198 /* Current declaration scope (top of the stack) (owned by this) */
199 struct ctx_decl_scope
*current_scope
;
201 /* True if trace declaration is visited */
202 bool is_trace_visited
;
204 /* True if this is an LTTng trace */
207 /* Config passed by the user */
208 struct ctf_metadata_decoder_config decoder_config
;
214 struct ctf_visitor_generate_ir
;
217 * Creates a new declaration scope.
219 * @param par_scope Parent scope (NULL if creating a root scope)
220 * @returns New declaration scope, or NULL on error
222 static struct ctx_decl_scope
*ctx_decl_scope_create(struct ctf_visitor_generate_ir
*ctx
,
223 struct ctx_decl_scope
*par_scope
)
225 struct ctx_decl_scope
*scope
;
227 scope
= g_new(struct ctx_decl_scope
, 1);
229 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate one declaration scope.");
233 scope
->decl_map
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
,
234 (GDestroyNotify
) ctf_field_class_destroy
);
235 scope
->parent_scope
= par_scope
;
242 * Destroys a declaration scope.
244 * This function does not destroy the parent scope.
246 * @param scope Scope to destroy
248 static void ctx_decl_scope_destroy(struct ctx_decl_scope
*scope
)
254 g_hash_table_destroy(scope
->decl_map
);
262 * Returns the GQuark of a prefixed alias.
264 * @param prefix Prefix character
266 * @returns Associated GQuark, or 0 on error
268 static GQuark
get_prefixed_named_quark(char prefix
, const char *name
)
271 std::string prname
= std::string
{prefix
} + name
;
272 return g_quark_from_string(prname
.c_str());
276 * Looks up a prefixed class alias within a declaration scope.
278 * @param scope Declaration scope
279 * @param prefix Prefix character
280 * @param name Alias name
281 * @param levels Number of levels to dig into (-1 means infinite)
282 * @param copy True to return a copy
283 * @returns Declaration (owned by caller if \p copy is true),
284 * or NULL if not found
286 static struct ctf_field_class
*ctx_decl_scope_lookup_prefix_alias(struct ctx_decl_scope
*scope
,
287 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(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 ctx_decl_scope
*scope
,
338 const char *name
, int levels
, bool copy
)
340 return ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ALIAS
, name
, levels
, copy
);
344 * Looks up an enumeration within a declaration scope.
346 * @param scope Declaration scope
347 * @param name Enumeration name
348 * @param levels Number of levels to dig into (-1 means infinite)
349 * @param copy True to return a copy
350 * @returns Declaration (owned by caller if \p copy is true),
351 * or NULL if not found
353 static struct ctf_field_class_enum
*
354 ctx_decl_scope_lookup_enum(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
356 return ctf_field_class_as_enum(
357 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_ENUM
, name
, levels
, copy
));
361 * Looks up a structure within a declaration scope.
363 * @param scope Declaration scope
364 * @param name Structure name
365 * @param levels Number of levels to dig into (-1 means infinite)
366 * @param copy True to return a copy
367 * @returns Declaration (owned by caller if \p copy is true),
368 * or NULL if not found
370 static struct ctf_field_class_struct
*
371 ctx_decl_scope_lookup_struct(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
373 return ctf_field_class_as_struct(
374 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_STRUCT
, name
, levels
, copy
));
378 * Looks up a variant within a declaration scope.
380 * @param scope Declaration scope
381 * @param name Variant name
382 * @param levels Number of levels to dig into (-1 means infinite)
383 * @param copy True to return a copy
384 * @returns Declaration (owned by caller if \p copy is true),
385 * or NULL if not found
387 static struct ctf_field_class_variant
*
388 ctx_decl_scope_lookup_variant(struct ctx_decl_scope
*scope
, const char *name
, int levels
, bool copy
)
390 return ctf_field_class_as_variant(
391 ctx_decl_scope_lookup_prefix_alias(scope
, _PREFIX_VARIANT
, name
, levels
, copy
));
395 * Registers a prefixed class alias within a declaration scope.
397 * @param scope Declaration scope
398 * @param prefix Prefix character
399 * @param name Alias name (non-NULL)
400 * @param decl Field class to register (copied)
401 * @returns 0 if registration went okay, negative value otherwise
403 static int ctx_decl_scope_register_prefix_alias(struct ctx_decl_scope
*scope
, char prefix
,
404 const char *name
, struct ctf_field_class
*decl
)
412 qname
= get_prefixed_named_quark(prefix
, name
);
418 /* Make sure alias does not exist in local scope */
419 if (ctx_decl_scope_lookup_prefix_alias(scope
, prefix
, name
, 1, false)) {
424 decl
= ctf_field_class_copy(decl
);
426 g_hash_table_insert(scope
->decl_map
, GUINT_TO_POINTER(qname
), decl
);
433 * Registers a class alias within a declaration scope.
435 * @param scope Declaration scope
436 * @param name Alias name (non-NULL)
437 * @param decl Field class to register (copied)
438 * @returns 0 if registration went okay, negative value otherwise
440 static int ctx_decl_scope_register_alias(struct ctx_decl_scope
*scope
, const char *name
,
441 struct ctf_field_class
*decl
)
443 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ALIAS
, name
, decl
);
447 * Registers an enumeration declaration within a declaration scope.
449 * @param scope Declaration scope
450 * @param name Enumeration name (non-NULL)
451 * @param decl Enumeration field class to register (copied)
452 * @returns 0 if registration went okay, negative value otherwise
454 static int ctx_decl_scope_register_enum(struct ctx_decl_scope
*scope
, const char *name
,
455 struct ctf_field_class_enum
*decl
)
457 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_ENUM
, name
, &decl
->base
.base
.base
);
461 * Registers a structure declaration within a declaration scope.
463 * @param scope Declaration scope
464 * @param name Structure name (non-NULL)
465 * @param decl Structure field class to register (copied)
466 * @returns 0 if registration went okay, negative value otherwise
468 static int ctx_decl_scope_register_struct(struct ctx_decl_scope
*scope
, const char *name
,
469 struct ctf_field_class_struct
*decl
)
471 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_STRUCT
, name
, &decl
->base
);
475 * Registers a variant declaration within a declaration scope.
477 * @param scope Declaration scope
478 * @param name Variant name (non-NULL)
479 * @param decl Variant field class to register
480 * @returns 0 if registration went okay, negative value otherwise
482 static int ctx_decl_scope_register_variant(struct ctx_decl_scope
*scope
, const char *name
,
483 struct ctf_field_class_variant
*decl
)
485 return ctx_decl_scope_register_prefix_alias(scope
, _PREFIX_VARIANT
, name
, &decl
->base
);
489 * Destroys a visitor context.
491 * @param ctx Visitor context to destroy
493 static void ctx_destroy(struct ctf_visitor_generate_ir
*ctx
)
495 struct ctx_decl_scope
*scope
;
501 scope
= ctx
->current_scope
;
504 * Destroy all scopes, from current one to the root scope.
507 struct ctx_decl_scope
*parent_scope
= scope
->parent_scope
;
509 ctx_decl_scope_destroy(scope
);
510 scope
= parent_scope
;
513 bt_trace_class_put_ref(ctx
->trace_class
);
516 ctf_trace_class_destroy(ctx
->ctf_tc
);
526 * Creates a new visitor context.
528 * @param trace Associated trace
529 * @returns New visitor context, or NULL on error
531 static struct ctf_visitor_generate_ir
*
532 ctx_create(const struct ctf_metadata_decoder_config
*decoder_config
)
534 struct ctf_visitor_generate_ir
*ctx
= NULL
;
536 BT_ASSERT(decoder_config
);
538 ctx
= g_new0(struct ctf_visitor_generate_ir
, 1);
540 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
, decoder_config
->self_comp
,
541 "Failed to allocate one visitor context.");
545 ctx
->log_cfg
.log_level
= decoder_config
->log_level
;
546 ctx
->log_cfg
.self_comp
= decoder_config
->self_comp
;
547 ctx
->log_cfg
.self_comp_class
= decoder_config
->self_comp_class
;
549 if (decoder_config
->self_comp
) {
550 ctx
->trace_class
= bt_trace_class_create(decoder_config
->self_comp
);
551 if (!ctx
->trace_class
) {
552 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create empty trace class.");
557 ctx
->ctf_tc
= ctf_trace_class_create();
559 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create CTF trace class.");
563 /* Root declaration scope */
564 ctx
->current_scope
= ctx_decl_scope_create(ctx
, NULL
);
565 if (!ctx
->current_scope
) {
566 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
570 ctx
->decoder_config
= *decoder_config
;
582 * Pushes a new declaration scope on top of a visitor context's
583 * declaration scope stack.
585 * @param ctx Visitor context
586 * @returns 0 on success, or a negative value on error
588 static int ctx_push_scope(struct ctf_visitor_generate_ir
*ctx
)
591 struct ctx_decl_scope
*new_scope
;
594 new_scope
= ctx_decl_scope_create(ctx
, ctx
->current_scope
);
596 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
601 ctx
->current_scope
= new_scope
;
607 static void ctx_pop_scope(struct ctf_visitor_generate_ir
*ctx
)
609 struct ctx_decl_scope
*parent_scope
= NULL
;
613 if (!ctx
->current_scope
) {
617 parent_scope
= ctx
->current_scope
->parent_scope
;
618 ctx_decl_scope_destroy(ctx
->current_scope
);
619 ctx
->current_scope
= parent_scope
;
625 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
626 struct ctf_node
*ts_list
,
627 struct ctf_field_class
**decl
);
629 static int is_unary_string(struct bt_list_head
*head
)
632 struct ctf_node
*node
;
634 bt_list_for_each_entry (node
, head
, siblings
) {
635 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
639 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
647 static const char *get_map_clock_name_value(struct bt_list_head
*head
)
650 struct ctf_node
*node
;
651 const char *name
= NULL
;
653 bt_list_for_each_entry (node
, head
, siblings
) {
655 int uexpr_type
= node
->u
.unary_expression
.type
;
656 int uexpr_link
= node
->u
.unary_expression
.link
;
657 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_STRING
||
658 !((uexpr_link
!= UNARY_LINK_UNKNOWN
) ^ (i
== 0));
663 /* Needs to be chained with . */
664 switch (node
->u
.unary_expression
.link
) {
667 case UNARY_ARROWLINK
:
668 case UNARY_DOTDOTDOT
:
674 src_string
= node
->u
.unary_expression
.u
.string
;
678 if (strcmp("clock", src_string
)) {
686 if (strcmp("value", src_string
)) {
691 /* Extra identifier, unknown */
704 static int is_unary_unsigned(struct bt_list_head
*head
)
707 struct ctf_node
*node
;
709 bt_list_for_each_entry (node
, head
, siblings
) {
710 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
714 if (node
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
722 static int get_unary_unsigned(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
727 struct ctf_node
*node
;
731 if (bt_list_empty(head
)) {
736 bt_list_for_each_entry (node
, head
, siblings
) {
737 int uexpr_type
= node
->u
.unary_expression
.type
;
738 int uexpr_link
= node
->u
.unary_expression
.link
;
739 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
|| uexpr_type
!= UNARY_UNSIGNED_CONSTANT
||
740 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
742 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid constant unsigned integer.");
747 *value
= node
->u
.unary_expression
.u
.unsigned_constant
;
755 static int is_unary_signed(struct bt_list_head
*head
)
758 struct ctf_node
*node
;
760 bt_list_for_each_entry (node
, head
, siblings
) {
761 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
765 if (node
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
) {
773 static int get_unary_signed(struct bt_list_head
*head
, int64_t *value
)
777 struct ctf_node
*node
;
779 bt_list_for_each_entry (node
, head
, siblings
) {
780 int uexpr_type
= node
->u
.unary_expression
.type
;
781 int uexpr_link
= node
->u
.unary_expression
.link
;
782 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
783 (uexpr_type
!= UNARY_UNSIGNED_CONSTANT
&& uexpr_type
!= UNARY_SIGNED_CONSTANT
) ||
784 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
790 switch (uexpr_type
) {
791 case UNARY_UNSIGNED_CONSTANT
:
792 *value
= (int64_t) node
->u
.unary_expression
.u
.unsigned_constant
;
794 case UNARY_SIGNED_CONSTANT
:
795 *value
= node
->u
.unary_expression
.u
.signed_constant
;
809 static int get_unary_uuid(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*head
,
812 return ctf_ast_get_unary_uuid(head
, uuid
, ctx
->log_cfg
.log_level
, ctx
->log_cfg
.self_comp
);
815 static int get_boolean(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*unary_expr
)
819 if (unary_expr
->type
!= NODE_UNARY_EXPRESSION
) {
820 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
, "Expecting unary expression: node-type=%d",
826 switch (unary_expr
->u
.unary_expression
.type
) {
827 case UNARY_UNSIGNED_CONSTANT
:
828 ret
= (unary_expr
->u
.unary_expression
.u
.unsigned_constant
!= 0);
830 case UNARY_SIGNED_CONSTANT
:
831 ret
= (unary_expr
->u
.unary_expression
.u
.signed_constant
!= 0);
835 const char *str
= unary_expr
->u
.unary_expression
.u
.string
;
837 if (strcmp(str
, "true") == 0 || strcmp(str
, "TRUE") == 0) {
839 } else if (strcmp(str
, "false") == 0 || strcmp(str
, "FALSE") == 0) {
842 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
, "Unexpected boolean value: value=\"%s\"",
850 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
851 "Unexpected unary expression type: node-type=%d",
852 unary_expr
->u
.unary_expression
.type
);
861 static enum ctf_byte_order
byte_order_from_unary_expr(struct ctf_visitor_generate_ir
*ctx
,
862 struct ctf_node
*unary_expr
)
865 enum ctf_byte_order bo
= CTF_BYTE_ORDER_UNKNOWN
;
867 if (unary_expr
->u
.unary_expression
.type
!= UNARY_STRING
) {
868 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
869 unary_expr
, "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
873 str
= unary_expr
->u
.unary_expression
.u
.string
;
875 if (strcmp(str
, "be") == 0 || strcmp(str
, "network") == 0) {
876 bo
= CTF_BYTE_ORDER_BIG
;
877 } else if (strcmp(str
, "le") == 0) {
878 bo
= CTF_BYTE_ORDER_LITTLE
;
879 } else if (strcmp(str
, "native") == 0) {
880 bo
= CTF_BYTE_ORDER_DEFAULT
;
882 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
884 "Unexpected \"byte_order\" attribute value: "
885 "expecting `be`, `le`, `network`, or `native`: value=\"%s\"",
894 static enum ctf_byte_order
get_real_byte_order(struct ctf_visitor_generate_ir
*ctx
,
895 struct ctf_node
*uexpr
)
897 enum ctf_byte_order bo
= byte_order_from_unary_expr(ctx
, uexpr
);
899 if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
900 bo
= ctx
->ctf_tc
->default_byte_order
;
906 static int is_align_valid(uint64_t align
)
908 return (align
!= 0) && !(align
& (align
- UINT64_C(1)));
911 static int get_class_specifier_name(struct ctf_visitor_generate_ir
*ctx
,
912 struct ctf_node
*cls_specifier
, GString
*str
)
916 if (cls_specifier
->type
!= NODE_TYPE_SPECIFIER
) {
917 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
, "Unexpected node type: node-type=%d",
918 cls_specifier
->type
);
923 switch (cls_specifier
->u
.field_class_specifier
.type
) {
925 g_string_append(str
, "void");
928 g_string_append(str
, "char");
931 g_string_append(str
, "short");
934 g_string_append(str
, "int");
937 g_string_append(str
, "long");
940 g_string_append(str
, "float");
942 case TYPESPEC_DOUBLE
:
943 g_string_append(str
, "double");
945 case TYPESPEC_SIGNED
:
946 g_string_append(str
, "signed");
948 case TYPESPEC_UNSIGNED
:
949 g_string_append(str
, "unsigned");
952 g_string_append(str
, "bool");
954 case TYPESPEC_COMPLEX
:
955 g_string_append(str
, "_Complex");
957 case TYPESPEC_IMAGINARY
:
958 g_string_append(str
, "_Imaginary");
961 g_string_append(str
, "const");
963 case TYPESPEC_ID_TYPE
:
964 if (cls_specifier
->u
.field_class_specifier
.id_type
) {
965 g_string_append(str
, cls_specifier
->u
.field_class_specifier
.id_type
);
968 case TYPESPEC_STRUCT
:
970 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
972 if (!node
->u
._struct
.name
) {
973 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty structure field class name.");
978 g_string_append(str
, "struct ");
979 g_string_append(str
, node
->u
._struct
.name
);
982 case TYPESPEC_VARIANT
:
984 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
986 if (!node
->u
.variant
.name
) {
987 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty variant field class name.");
992 g_string_append(str
, "variant ");
993 g_string_append(str
, node
->u
.variant
.name
);
998 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1000 if (!node
->u
._enum
.enum_id
) {
1001 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1002 node
, "Unexpected empty enumeration field class (`enum`) name.");
1007 g_string_append(str
, "enum ");
1008 g_string_append(str
, node
->u
._enum
.enum_id
);
1011 case TYPESPEC_FLOATING_POINT
:
1012 case TYPESPEC_INTEGER
:
1013 case TYPESPEC_STRING
:
1015 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier
->u
.field_class_specifier
.node
,
1016 "Unexpected field class specifier type: %d",
1017 cls_specifier
->u
.field_class_specifier
.type
);
1026 static int get_class_specifier_list_name(struct ctf_visitor_generate_ir
*ctx
,
1027 struct ctf_node
*cls_specifier_list
, GString
*str
)
1030 struct ctf_node
*iter
;
1031 int alias_item_nr
= 0;
1032 struct bt_list_head
*head
= &cls_specifier_list
->u
.field_class_specifier_list
.head
;
1034 bt_list_for_each_entry (iter
, head
, siblings
) {
1035 if (alias_item_nr
!= 0) {
1036 g_string_append(str
, " ");
1040 ret
= get_class_specifier_name(ctx
, iter
, str
);
1050 static GQuark
create_class_alias_identifier(struct ctf_visitor_generate_ir
*ctx
,
1051 struct ctf_node
*cls_specifier_list
,
1052 struct ctf_node
*node_field_class_declarator
)
1058 struct ctf_node
*iter
;
1059 struct bt_list_head
*pointers
= &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1061 str
= g_string_new("");
1062 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
1064 g_string_free(str
, TRUE
);
1068 bt_list_for_each_entry (iter
, pointers
, siblings
) {
1069 g_string_append(str
, " *");
1071 if (iter
->u
.pointer
.const_qualifier
) {
1072 g_string_append(str
, " const");
1076 str_c
= g_string_free(str
, FALSE
);
1077 qalias
= g_quark_from_string(str_c
);
1084 static int visit_field_class_declarator(struct ctf_visitor_generate_ir
*ctx
,
1085 struct ctf_node
*cls_specifier_list
, GQuark
*field_name
,
1086 struct ctf_node
*node_field_class_declarator
,
1087 struct ctf_field_class
**field_decl
,
1088 struct ctf_field_class
*nested_decl
)
1091 * During this whole function, nested_decl is always OURS,
1092 * whereas field_decl is an output which we create, but
1093 * belongs to the caller (it is moved).
1098 /* Validate field class declarator node */
1099 if (node_field_class_declarator
) {
1100 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_UNKNOWN
) {
1101 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1102 node_field_class_declarator
, "Unexpected field class declarator type: type=%d",
1103 node_field_class_declarator
->u
.field_class_declarator
.type
);
1108 /* TODO: GCC bitfields not supported yet */
1109 if (node_field_class_declarator
->u
.field_class_declarator
.bitfield_len
!= NULL
) {
1110 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1111 "GCC bitfields are not supported as of this version.");
1117 /* Find the right nested declaration if not provided */
1119 if (node_field_class_declarator
&&
1120 !bt_list_empty(&node_field_class_declarator
->u
.field_class_declarator
.pointers
)) {
1124 * If we have a pointer declarator, it HAS to
1125 * be present in the field class aliases (else
1129 create_class_alias_identifier(ctx
, cls_specifier_list
, node_field_class_declarator
);
1130 nested_decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, g_quark_to_string(qalias
),
1133 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1134 "Cannot find class alias: name=\"%s\"",
1135 g_quark_to_string(qalias
));
1140 if (nested_decl
->type
== CTF_FIELD_CLASS_TYPE_INT
) {
1141 /* Pointer: force integer's base to 16 */
1142 struct ctf_field_class_int
*int_fc
= ctf_field_class_as_int(nested_decl
);
1144 int_fc
->disp_base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
1147 ret
= visit_field_class_specifier_list(ctx
, cls_specifier_list
, &nested_decl
);
1149 BT_ASSERT(!nested_decl
);
1155 BT_ASSERT(nested_decl
);
1157 if (!node_field_class_declarator
) {
1158 *field_decl
= nested_decl
;
1163 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_ID
) {
1164 if (node_field_class_declarator
->u
.field_class_declarator
.u
.id
) {
1165 const char *id
= node_field_class_declarator
->u
.field_class_declarator
.u
.id
;
1167 *field_name
= g_quark_from_string(id
);
1172 *field_decl
= nested_decl
;
1176 struct ctf_node
*first
;
1177 struct ctf_field_class
*decl
= NULL
;
1178 struct ctf_field_class
*outer_field_decl
= NULL
;
1179 struct bt_list_head
*length
=
1180 &node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.length
;
1182 /* Create array/sequence, pass nested_decl as child */
1183 if (bt_list_empty(length
)) {
1184 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1185 "Expecting length field reference or value.");
1190 first
= _BT_LIST_FIRST_ENTRY(length
, struct ctf_node
, siblings
);
1191 if (first
->type
!= NODE_UNARY_EXPRESSION
) {
1192 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type=%d",
1198 switch (first
->u
.unary_expression
.type
) {
1199 case UNARY_UNSIGNED_CONSTANT
:
1201 struct ctf_field_class_array
*array_decl
= NULL
;
1203 array_decl
= ctf_field_class_array_create();
1204 BT_ASSERT(array_decl
);
1205 array_decl
->length
= first
->u
.unary_expression
.u
.unsigned_constant
;
1206 array_decl
->base
.elem_fc
= nested_decl
;
1208 decl
= &array_decl
->base
.base
;
1213 /* Lookup unsigned integer definition, create seq. */
1214 struct ctf_field_class_sequence
*seq_decl
= NULL
;
1215 char *length_name
= ctf_ast_concatenate_unary_strings(length
);
1218 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1219 "Cannot concatenate unary strings.");
1224 if (strncmp(length_name
, "env.", 4) == 0) {
1225 /* This is, in fact, an array */
1226 const char *env_entry_name
= &length_name
[4];
1227 struct ctf_trace_class_env_entry
*env_entry
=
1228 ctf_trace_class_borrow_env_entry_by_name(ctx
->ctf_tc
, env_entry_name
);
1229 struct ctf_field_class_array
*array_decl
;
1232 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1233 "Cannot find environment entry: "
1240 if (env_entry
->type
!= CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
) {
1241 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1242 "Wrong environment entry type "
1243 "(expecting integer): "
1250 if (env_entry
->value
.i
< 0) {
1251 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1252 "Invalid, negative array length: "
1253 "env-entry-name=\"%s\", "
1255 env_entry_name
, env_entry
->value
.i
);
1260 array_decl
= ctf_field_class_array_create();
1261 BT_ASSERT(array_decl
);
1262 array_decl
->length
= (uint64_t) env_entry
->value
.i
;
1263 array_decl
->base
.elem_fc
= nested_decl
;
1265 decl
= &array_decl
->base
.base
;
1267 seq_decl
= ctf_field_class_sequence_create();
1268 BT_ASSERT(seq_decl
);
1269 seq_decl
->base
.elem_fc
= nested_decl
;
1271 g_string_assign(seq_decl
->length_ref
, length_name
);
1272 decl
= &seq_decl
->base
.base
;
1275 g_free(length_name
);
1283 BT_ASSERT(!nested_decl
);
1285 BT_ASSERT(!*field_decl
);
1288 * At this point, we found the next nested declaration.
1289 * We currently own this (and lost the ownership of
1290 * nested_decl in the meantime). Pass this next
1291 * nested declaration as the content of the outer
1292 * container, MOVING its ownership.
1294 ret
= visit_field_class_declarator(
1295 ctx
, cls_specifier_list
, field_name
,
1296 node_field_class_declarator
->u
.field_class_declarator
.u
.nested
.field_class_declarator
,
1297 &outer_field_decl
, decl
);
1300 BT_ASSERT(!outer_field_decl
);
1305 BT_ASSERT(outer_field_decl
);
1306 *field_decl
= outer_field_decl
;
1307 outer_field_decl
= NULL
;
1310 BT_ASSERT(*field_decl
);
1314 ctf_field_class_destroy(*field_decl
);
1322 ctf_field_class_destroy(nested_decl
);
1327 static int visit_struct_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1328 struct ctf_field_class_struct
*struct_decl
,
1329 struct ctf_node
*cls_specifier_list
,
1330 struct bt_list_head
*field_class_declarators
)
1333 struct ctf_node
*iter
;
1334 struct ctf_field_class
*field_decl
= NULL
;
1336 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1339 const char *field_name
;
1341 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1344 BT_ASSERT(!field_decl
);
1345 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1346 "Cannot visit field class declarator: ret=%d", ret
);
1350 BT_ASSERT(field_decl
);
1351 field_name
= g_quark_to_string(qfield_name
);
1353 /* Check if field with same name already exists */
1354 if (ctf_field_class_struct_borrow_member_by_name(struct_decl
, field_name
)) {
1355 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1356 "Duplicate field in structure field class: "
1357 "field-name=\"%s\"",
1363 /* Add field to structure */
1364 ctf_field_class_struct_append_member(struct_decl
, field_name
, field_decl
);
1371 ctf_field_class_destroy(field_decl
);
1376 static int visit_variant_decl_field(struct ctf_visitor_generate_ir
*ctx
,
1377 struct ctf_field_class_variant
*variant_decl
,
1378 struct ctf_node
*cls_specifier_list
,
1379 struct bt_list_head
*field_class_declarators
)
1382 struct ctf_node
*iter
;
1383 struct ctf_field_class
*field_decl
= NULL
;
1385 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1388 const char *field_name
;
1390 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qfield_name
, iter
, &field_decl
,
1393 BT_ASSERT(!field_decl
);
1394 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1395 "Cannot visit field class declarator: ret=%d", ret
);
1399 BT_ASSERT(field_decl
);
1400 field_name
= g_quark_to_string(qfield_name
);
1402 /* Check if field with same name already exists */
1403 if (ctf_field_class_variant_borrow_option_by_name(variant_decl
, field_name
)) {
1404 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1405 "Duplicate field in variant field class: "
1406 "field-name=\"%s\"",
1412 /* Add field to structure */
1413 ctf_field_class_variant_append_option(variant_decl
, field_name
, field_decl
);
1420 ctf_field_class_destroy(field_decl
);
1425 static int visit_field_class_def(struct ctf_visitor_generate_ir
*ctx
,
1426 struct ctf_node
*cls_specifier_list
,
1427 struct bt_list_head
*field_class_declarators
)
1431 struct ctf_node
*iter
;
1432 struct ctf_field_class
*class_decl
= NULL
;
1434 bt_list_for_each_entry (iter
, field_class_declarators
, siblings
) {
1435 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
, &qidentifier
, iter
, &class_decl
,
1438 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit field class declarator: ret=%d",
1444 /* Do not allow field class def and alias of untagged variants */
1445 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1446 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1448 if (var_fc
->tag_path
.path
->len
== 0) {
1449 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1450 iter
, "Type definition of untagged variant field class is not allowed.");
1456 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qidentifier
),
1459 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot register field class alias: name=\"%s\"",
1460 g_quark_to_string(qidentifier
));
1466 ctf_field_class_destroy(class_decl
);
1471 static int visit_field_class_alias(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*target
,
1472 struct ctf_node
*alias
)
1476 struct ctf_node
*node
;
1477 GQuark qdummy_field_name
;
1478 struct ctf_field_class
*class_decl
= NULL
;
1480 /* Create target field class */
1481 if (bt_list_empty(&target
->u
.field_class_alias_target
.field_class_declarators
)) {
1484 node
= _BT_LIST_FIRST_ENTRY(&target
->u
.field_class_alias_target
.field_class_declarators
,
1485 struct ctf_node
, siblings
);
1488 ret
= visit_field_class_declarator(
1489 ctx
, target
->u
.field_class_alias_target
.field_class_specifier_list
, &qdummy_field_name
,
1490 node
, &class_decl
, NULL
);
1492 BT_ASSERT(!class_decl
);
1493 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot visit field class declarator: ret=%d", ret
);
1497 /* Do not allow field class def and alias of untagged variants */
1498 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1499 struct ctf_field_class_variant
*var_fc
= ctf_field_class_as_variant(class_decl
);
1501 if (var_fc
->tag_path
.path
->len
== 0) {
1502 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1503 target
, "Type definition of untagged variant field class is not allowed.");
1510 * The semantic validator does not check whether the target is
1511 * abstract or not (if it has an identifier). Check it here.
1513 if (qdummy_field_name
!= 0) {
1514 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target
, "Expecting empty identifier: id=\"%s\"",
1515 g_quark_to_string(qdummy_field_name
));
1520 /* Create alias identifier */
1521 node
= _BT_LIST_FIRST_ENTRY(&alias
->u
.field_class_alias_name
.field_class_declarators
,
1522 struct ctf_node
, siblings
);
1523 qalias
= create_class_alias_identifier(
1524 ctx
, alias
->u
.field_class_alias_name
.field_class_specifier_list
, node
);
1525 ret
= ctx_decl_scope_register_alias(ctx
->current_scope
, g_quark_to_string(qalias
), class_decl
);
1527 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot register class alias: name=\"%s\"",
1528 g_quark_to_string(qalias
));
1533 ctf_field_class_destroy(class_decl
);
1538 static int visit_struct_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
1539 struct ctf_field_class_struct
*struct_decl
)
1543 switch (entry_node
->type
) {
1545 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1546 &entry_node
->u
.field_class_def
.field_class_declarators
);
1548 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1549 entry_node
, "Cannot add field class found in structure field class: ret=%d", ret
);
1553 case NODE_TYPEALIAS
:
1554 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1555 entry_node
->u
.field_class_alias
.alias
);
1557 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1558 entry_node
, "Cannot add field class alias found in structure field class: ret=%d",
1563 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1565 ret
= visit_struct_decl_field(
1567 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1568 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1574 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
1584 static int visit_variant_decl_entry(struct ctf_visitor_generate_ir
*ctx
,
1585 struct ctf_node
*entry_node
,
1586 struct ctf_field_class_variant
*variant_decl
)
1590 switch (entry_node
->type
) {
1592 ret
= visit_field_class_def(ctx
, entry_node
->u
.field_class_def
.field_class_specifier_list
,
1593 &entry_node
->u
.field_class_def
.field_class_declarators
);
1595 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1596 entry_node
, "Cannot add field class found in variant field class: ret=%d", ret
);
1600 case NODE_TYPEALIAS
:
1601 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1602 entry_node
->u
.field_class_alias
.alias
);
1604 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1605 entry_node
, "Cannot add field class alias found in variant field class: ret=%d",
1610 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1612 ret
= visit_variant_decl_field(
1614 entry_node
->u
.struct_or_variant_declaration
.field_class_specifier_list
,
1615 &entry_node
->u
.struct_or_variant_declaration
.field_class_declarators
);
1621 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
1631 static int visit_struct_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1632 struct bt_list_head
*decl_list
, int has_body
,
1633 struct bt_list_head
*min_align
,
1634 struct ctf_field_class_struct
**struct_decl
)
1638 BT_ASSERT(struct_decl
);
1639 *struct_decl
= NULL
;
1641 /* For named struct (without body), lookup in declaration scope */
1644 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1645 "Bodyless structure field class: missing name.");
1650 *struct_decl
= ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, -1, true);
1651 if (!*struct_decl
) {
1652 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1653 "Cannot find structure field class: name=\"struct %s\"", name
);
1658 struct ctf_node
*entry_node
;
1659 uint64_t min_align_value
= 0;
1662 if (ctx_decl_scope_lookup_struct(ctx
->current_scope
, name
, 1, false)) {
1663 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1664 "Structure field class already declared in local scope: "
1665 "name=\"struct %s\"",
1672 if (!bt_list_empty(min_align
)) {
1673 ret
= get_unary_unsigned(ctx
, min_align
, &min_align_value
);
1675 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1676 "Unexpected unary expression for structure field class's `align` attribute: "
1683 *struct_decl
= ctf_field_class_struct_create();
1684 BT_ASSERT(*struct_decl
);
1686 if (min_align_value
!= 0) {
1687 (*struct_decl
)->base
.alignment
= min_align_value
;
1690 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1692 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1693 ret
= visit_struct_decl_entry(ctx
, entry_node
, *struct_decl
);
1695 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1696 "Cannot visit structure field class entry: "
1707 ret
= ctx_decl_scope_register_struct(ctx
->current_scope
, name
, *struct_decl
);
1709 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1710 "Cannot register structure field class in declaration scope: "
1711 "name=\"struct %s\", ret=%d",
1721 ctf_field_class_destroy(&(*struct_decl
)->base
);
1722 *struct_decl
= NULL
;
1726 static int visit_variant_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1727 const char *tag
, struct bt_list_head
*decl_list
, int has_body
,
1728 struct ctf_field_class_variant
**variant_decl
)
1731 struct ctf_field_class_variant
*untagged_variant_decl
= NULL
;
1733 BT_ASSERT(variant_decl
);
1734 *variant_decl
= NULL
;
1736 /* For named variant (without body), lookup in declaration scope */
1739 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name.");
1744 untagged_variant_decl
= ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, -1, true);
1745 if (!untagged_variant_decl
) {
1746 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1747 "Cannot find variant field class: name=\"variant %s\"", name
);
1752 struct ctf_node
*entry_node
;
1755 if (ctx_decl_scope_lookup_variant(ctx
->current_scope
, name
, 1, false)) {
1756 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1757 "Variant field class already declared in local scope: "
1758 "name=\"variant %s\"",
1765 untagged_variant_decl
= ctf_field_class_variant_create();
1766 BT_ASSERT(untagged_variant_decl
);
1767 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1769 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
1770 ret
= visit_variant_decl_entry(ctx
, entry_node
, untagged_variant_decl
);
1772 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1773 "Cannot visit variant field class entry: "
1784 ret
= ctx_decl_scope_register_variant(ctx
->current_scope
, name
, untagged_variant_decl
);
1786 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1787 "Cannot register variant field class in declaration scope: "
1788 "name=\"variant %s\", ret=%d",
1796 * If tagged, create tagged variant and return; otherwise
1797 * return untagged variant.
1800 *variant_decl
= untagged_variant_decl
;
1801 untagged_variant_decl
= NULL
;
1804 * At this point, we have a fresh untagged variant; nobody
1805 * else owns it. Set its tag now.
1807 g_string_assign(untagged_variant_decl
->tag_ref
, tag
);
1808 *variant_decl
= untagged_variant_decl
;
1809 untagged_variant_decl
= NULL
;
1812 BT_ASSERT(!untagged_variant_decl
);
1813 BT_ASSERT(*variant_decl
);
1817 ctf_field_class_destroy(&untagged_variant_decl
->base
);
1818 untagged_variant_decl
= NULL
;
1819 ctf_field_class_destroy(&(*variant_decl
)->base
);
1820 *variant_decl
= NULL
;
1834 static int visit_enum_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*enumerator
,
1835 struct ctf_field_class_enum
*enum_decl
, struct uori
*last
)
1839 struct ctf_node
*iter
;
1840 struct uori start
= {
1854 const char *label
= enumerator
->u
.enumerator
.id
;
1855 struct bt_list_head
*values
= &enumerator
->u
.enumerator
.values
;
1857 bt_list_for_each_entry (iter
, values
, siblings
) {
1858 struct uori
*target
;
1860 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
1861 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1862 "Wrong expression for enumeration field class label: "
1863 "node-type=%d, label=\"%s\"",
1875 switch (iter
->u
.unary_expression
.type
) {
1876 case UNARY_SIGNED_CONSTANT
:
1877 target
->is_signed
= true;
1878 target
->value
.i
= iter
->u
.unary_expression
.u
.signed_constant
;
1880 case UNARY_UNSIGNED_CONSTANT
:
1881 target
->is_signed
= false;
1882 target
->value
.u
= iter
->u
.unary_expression
.u
.unsigned_constant
;
1885 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1886 "Invalid enumeration field class entry: "
1887 "expecting constant signed or unsigned integer: "
1888 "node-type=%d, label=\"%s\"",
1889 iter
->u
.unary_expression
.type
, label
);
1895 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1896 iter
, "Invalid enumeration field class entry: label=\"%s\"", label
);
1912 if (end
.is_signed
) {
1913 last
->value
.i
= end
.value
.i
+ 1;
1915 last
->value
.u
= end
.value
.u
+ 1;
1918 ctf_field_class_enum_map_range(enum_decl
, label
, start
.value
.u
, end
.value
.u
);
1925 static int visit_enum_decl(struct ctf_visitor_generate_ir
*ctx
, const char *name
,
1926 struct ctf_node
*container_cls
, struct bt_list_head
*enumerator_list
,
1927 int has_body
, struct ctf_field_class_enum
**enum_decl
)
1931 struct ctf_field_class_int
*integer_decl
= NULL
;
1933 BT_ASSERT(enum_decl
);
1936 /* For named enum (without body), lookup in declaration scope */
1939 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1940 "Bodyless enumeration field class: missing name.");
1945 *enum_decl
= ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, -1, true);
1947 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: "
1954 struct ctf_node
*iter
;
1955 struct uori last_value
= {
1964 if (ctx_decl_scope_lookup_enum(ctx
->current_scope
, name
, 1, false)) {
1965 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1966 "Enumeration field class already declared in local scope: "
1974 if (!container_cls
) {
1975 integer_decl
= ctf_field_class_as_int(
1976 ctx_decl_scope_lookup_alias(ctx
->current_scope
, "int", -1, true));
1977 if (!integer_decl
) {
1978 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1979 "Cannot find implicit `int` field class alias for enumeration field class.");
1984 ctf_field_class
*decl
;
1986 ret
= visit_field_class_declarator(ctx
, container_cls
, &qdummy_id
, NULL
, &decl
, NULL
);
1993 integer_decl
= ctf_field_class_as_int(decl
);
1996 BT_ASSERT(integer_decl
);
1998 if (integer_decl
->base
.base
.type
!= CTF_FIELD_CLASS_TYPE_INT
) {
1999 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2000 "Container field class for enumeration field class is not an integer field class: "
2002 integer_decl
->base
.base
.type
);
2007 *enum_decl
= ctf_field_class_enum_create();
2008 BT_ASSERT(*enum_decl
);
2009 (*enum_decl
)->base
.base
.base
.alignment
= integer_decl
->base
.base
.alignment
;
2010 ctf_field_class_int_copy_content(&(*enum_decl
)->base
, integer_decl
);
2011 last_value
.is_signed
= (*enum_decl
)->base
.is_signed
;
2013 bt_list_for_each_entry (iter
, enumerator_list
, siblings
) {
2014 ret
= visit_enum_decl_entry(ctx
, iter
, *enum_decl
, &last_value
);
2016 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
2017 "Cannot visit enumeration field class entry: "
2025 ret
= ctx_decl_scope_register_enum(ctx
->current_scope
, name
, *enum_decl
);
2027 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2028 "Cannot register enumeration field class in declaration scope: "
2039 ctf_field_class_destroy(&(*enum_decl
)->base
.base
.base
);
2043 ctf_field_class_destroy(&integer_decl
->base
.base
);
2044 integer_decl
= NULL
;
2048 static int visit_field_class_specifier(struct ctf_visitor_generate_ir
*ctx
,
2049 struct ctf_node
*cls_specifier_list
,
2050 struct ctf_field_class
**decl
)
2053 GString
*str
= NULL
;
2056 str
= g_string_new("");
2057 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
2059 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2060 cls_specifier_list
, "Cannot get field class specifier list's name: ret=%d", ret
);
2064 *decl
= ctx_decl_scope_lookup_alias(ctx
->current_scope
, str
->str
, -1, true);
2066 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2067 "Cannot find field class alias: name=\"%s\"", str
->str
);
2075 ctf_field_class_destroy(*decl
);
2080 g_string_free(str
, TRUE
);
2086 static int visit_integer_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2087 struct ctf_field_class_int
**integer_decl
)
2092 struct ctf_node
*expression
;
2093 uint64_t alignment
= 0, size
= 0;
2094 struct ctf_clock_class
*mapped_clock_class
= NULL
;
2095 enum ctf_encoding encoding
= CTF_ENCODING_NONE
;
2096 bt_field_class_integer_preferred_display_base base
=
2097 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2098 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2100 *integer_decl
= NULL
;
2102 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2103 struct ctf_node
*left
, *right
;
2105 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2107 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2109 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2110 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2111 left
->u
.unary_expression
.type
);
2116 if (strcmp(left
->u
.unary_expression
.u
.string
, "signed") == 0) {
2117 if (_IS_SET(&set
, _INTEGER_SIGNED_SET
)) {
2118 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "signed", "integer field class");
2123 signedness
= get_boolean(ctx
, right
);
2124 if (signedness
< 0) {
2125 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2127 "Invalid boolean value for integer field class's `signed` attribute: "
2134 _SET(&set
, _INTEGER_SIGNED_SET
);
2135 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2136 if (_IS_SET(&set
, _INTEGER_BYTE_ORDER_SET
)) {
2137 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order", "integer field class");
2142 byte_order
= get_real_byte_order(ctx
, right
);
2143 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2144 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2146 "Invalid `byte_order` attribute in integer field class: "
2153 _SET(&set
, _INTEGER_BYTE_ORDER_SET
);
2154 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "size") == 0) {
2155 if (_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2156 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "size", "integer field class");
2161 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2162 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2163 "Invalid `size` attribute in integer field class: "
2164 "expecting unsigned constant integer: "
2166 right
->u
.unary_expression
.type
);
2171 size
= right
->u
.unary_expression
.u
.unsigned_constant
;
2173 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2174 "Invalid `size` attribute in integer field class: "
2175 "expecting positive constant integer: "
2180 } else if (size
> 64) {
2181 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2183 "Invalid `size` attribute in integer field class: "
2184 "integer fields over 64 bits are not supported as of this version: "
2191 _SET(&set
, _INTEGER_SIZE_SET
);
2192 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2193 if (_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2194 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align", "integer field class");
2199 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2200 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2201 "Invalid `align` attribute in integer field class: "
2202 "expecting unsigned constant integer: "
2204 right
->u
.unary_expression
.type
);
2209 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2210 if (!is_align_valid(alignment
)) {
2211 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2212 "Invalid `align` attribute in integer field class: "
2213 "expecting power of two: "
2220 _SET(&set
, _INTEGER_ALIGN_SET
);
2221 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "base") == 0) {
2222 if (_IS_SET(&set
, _INTEGER_BASE_SET
)) {
2223 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "base", "integer field class");
2228 switch (right
->u
.unary_expression
.type
) {
2229 case UNARY_UNSIGNED_CONSTANT
:
2231 uint64_t constant
= right
->u
.unary_expression
.u
.unsigned_constant
;
2235 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2238 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2241 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2244 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2247 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2249 "Invalid `base` attribute in integer field class: "
2251 right
->u
.unary_expression
.u
.unsigned_constant
);
2260 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2262 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2264 "Unexpected unary expression for integer field class's `base` attribute.");
2269 if (strcmp(s_right
, "decimal") == 0 || strcmp(s_right
, "dec") == 0 ||
2270 strcmp(s_right
, "d") == 0 || strcmp(s_right
, "i") == 0 ||
2271 strcmp(s_right
, "u") == 0) {
2272 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2273 } else if (strcmp(s_right
, "hexadecimal") == 0 || strcmp(s_right
, "hex") == 0 ||
2274 strcmp(s_right
, "x") == 0 || strcmp(s_right
, "X") == 0 ||
2275 strcmp(s_right
, "p") == 0) {
2276 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2277 } else if (strcmp(s_right
, "octal") == 0 || strcmp(s_right
, "oct") == 0 ||
2278 strcmp(s_right
, "o") == 0) {
2279 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2280 } else if (strcmp(s_right
, "binary") == 0 || strcmp(s_right
, "b") == 0) {
2281 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2283 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2285 "Unexpected unary expression for integer field class's `base` attribute: "
2297 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2298 right
, "Invalid `base` attribute in integer field class: "
2299 "expecting unsigned constant integer or unary string.");
2304 _SET(&set
, _INTEGER_BASE_SET
);
2305 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2308 if (_IS_SET(&set
, _INTEGER_ENCODING_SET
)) {
2309 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "integer field class");
2314 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2315 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2316 right
, "Invalid `encoding` attribute in integer field class: "
2317 "expecting unary string.");
2322 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2324 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2326 "Unexpected unary expression for integer field class's `encoding` attribute.");
2331 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2332 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2333 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2334 encoding
= CTF_ENCODING_UTF8
;
2335 } else if (strcmp(s_right
, "none") == 0) {
2336 encoding
= CTF_ENCODING_NONE
;
2338 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2340 "Invalid `encoding` attribute in integer field class: "
2341 "unknown encoding: encoding=\"%s\"",
2349 _SET(&set
, _INTEGER_ENCODING_SET
);
2350 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "map") == 0) {
2351 const char *clock_name
;
2353 if (_IS_SET(&set
, _INTEGER_MAP_SET
)) {
2354 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "map", "integer field class");
2359 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2360 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2361 "Invalid `map` attribute in integer field class: "
2362 "expecting unary string.");
2367 clock_name
= get_map_clock_name_value(&expression
->u
.ctf_expression
.right
);
2370 ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2373 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2375 "Unexpected unary expression for integer field class's `map` attribute.");
2380 _BT_COMP_LOGE_NODE(right
,
2381 "Invalid `map` attribute in integer field class: "
2382 "cannot find clock class at this point: name=\"%s\"",
2384 _SET(&set
, _INTEGER_MAP_SET
);
2389 mapped_clock_class
=
2390 ctf_trace_class_borrow_clock_class_by_name(ctx
->ctf_tc
, clock_name
);
2391 if (!mapped_clock_class
) {
2392 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2394 "Invalid `map` attribute in integer field class: "
2395 "cannot find clock class at this point: name=\"%s\"",
2401 _SET(&set
, _INTEGER_MAP_SET
);
2403 _BT_COMP_LOGW_NODE(left
,
2404 "Unknown attribute in integer field class: "
2406 left
->u
.unary_expression
.u
.string
);
2410 if (!_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2411 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2412 "Missing `size` attribute in integer field class.");
2417 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2418 if (size
% CHAR_BIT
) {
2419 /* Bit-packed alignment */
2422 /* Byte-packed alignment */
2423 alignment
= CHAR_BIT
;
2427 *integer_decl
= ctf_field_class_int_create();
2428 BT_ASSERT(*integer_decl
);
2429 (*integer_decl
)->base
.base
.alignment
= alignment
;
2430 (*integer_decl
)->base
.byte_order
= byte_order
;
2431 (*integer_decl
)->base
.size
= size
;
2432 (*integer_decl
)->is_signed
= (signedness
> 0);
2433 (*integer_decl
)->disp_base
= base
;
2434 (*integer_decl
)->encoding
= encoding
;
2435 (*integer_decl
)->mapped_clock_class
= mapped_clock_class
;
2439 ctf_field_class_destroy(&(*integer_decl
)->base
.base
);
2440 *integer_decl
= NULL
;
2444 static int visit_floating_point_number_decl(struct ctf_visitor_generate_ir
*ctx
,
2445 struct bt_list_head
*expressions
,
2446 struct ctf_field_class_float
**float_decl
)
2450 struct ctf_node
*expression
;
2451 uint64_t alignment
= 1, exp_dig
= 0, mant_dig
= 0;
2452 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2456 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2457 struct ctf_node
*left
, *right
;
2459 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2461 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2463 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2464 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2465 left
->u
.unary_expression
.type
);
2470 if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2471 if (_IS_SET(&set
, _FLOAT_BYTE_ORDER_SET
)) {
2472 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "byte_order",
2473 "floating point number field class");
2478 byte_order
= get_real_byte_order(ctx
, right
);
2479 if (byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
2480 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2482 "Invalid `byte_order` attribute in floating point number field class: "
2489 _SET(&set
, _FLOAT_BYTE_ORDER_SET
);
2490 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "exp_dig") == 0) {
2491 if (_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2492 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "exp_dig",
2493 "floating point number field class");
2498 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2499 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2501 "Invalid `exp_dig` attribute in floating point number field class: "
2502 "expecting unsigned constant integer: "
2504 right
->u
.unary_expression
.type
);
2509 exp_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2510 _SET(&set
, _FLOAT_EXP_DIG_SET
);
2511 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "mant_dig") == 0) {
2512 if (_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2513 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "mant_dig",
2514 "floating point number field class");
2519 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2520 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2522 "Invalid `mant_dig` attribute in floating point number field class: "
2523 "expecting unsigned constant integer: "
2525 right
->u
.unary_expression
.type
);
2530 mant_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2531 _SET(&set
, _FLOAT_MANT_DIG_SET
);
2532 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2533 if (_IS_SET(&set
, _FLOAT_ALIGN_SET
)) {
2534 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "align",
2535 "floating point number field class");
2540 if (right
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
2541 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2543 "Invalid `align` attribute in floating point number field class: "
2544 "expecting unsigned constant integer: "
2546 right
->u
.unary_expression
.type
);
2551 alignment
= right
->u
.unary_expression
.u
.unsigned_constant
;
2553 if (!is_align_valid(alignment
)) {
2554 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2556 "Invalid `align` attribute in floating point number field class: "
2557 "expecting power of two: "
2564 _SET(&set
, _FLOAT_ALIGN_SET
);
2566 _BT_COMP_LOGW_NODE(left
,
2567 "Unknown attribute in floating point number field class: "
2569 left
->u
.unary_expression
.u
.string
);
2573 if (!_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2574 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2575 "Missing `mant_dig` attribute in floating point number field class.");
2580 if (!_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2581 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2582 "Missing `exp_dig` attribute in floating point number field class.");
2587 if (mant_dig
!= 24 && mant_dig
!= 53) {
2588 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53.");
2593 if (mant_dig
== 24 && exp_dig
!= 8) {
2594 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2595 "`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2600 if (mant_dig
== 53 && exp_dig
!= 11) {
2601 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2602 "`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2607 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2608 if ((mant_dig
+ exp_dig
) % CHAR_BIT
) {
2609 /* Bit-packed alignment */
2612 /* Byte-packed alignment */
2613 alignment
= CHAR_BIT
;
2617 *float_decl
= ctf_field_class_float_create();
2618 BT_ASSERT(*float_decl
);
2619 (*float_decl
)->base
.base
.alignment
= alignment
;
2620 (*float_decl
)->base
.byte_order
= byte_order
;
2621 (*float_decl
)->base
.size
= mant_dig
+ exp_dig
;
2625 ctf_field_class_destroy(&(*float_decl
)->base
.base
);
2630 static int visit_string_decl(struct ctf_visitor_generate_ir
*ctx
, struct bt_list_head
*expressions
,
2631 struct ctf_field_class_string
**string_decl
)
2635 struct ctf_node
*expression
;
2636 enum ctf_encoding encoding
= CTF_ENCODING_UTF8
;
2638 *string_decl
= NULL
;
2640 bt_list_for_each_entry (expression
, expressions
, siblings
) {
2641 struct ctf_node
*left
, *right
;
2643 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
, struct ctf_node
, siblings
);
2645 _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
2647 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2648 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left
, "Unexpected unary expression type: type=%d",
2649 left
->u
.unary_expression
.type
);
2654 if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2657 if (_IS_SET(&set
, _STRING_ENCODING_SET
)) {
2658 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding", "string field class");
2663 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2664 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2665 right
, "Invalid `encoding` attribute in string field class: "
2666 "expecting unary string.");
2671 s_right
= ctf_ast_concatenate_unary_strings(&expression
->u
.ctf_expression
.right
);
2673 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2675 "Unexpected unary expression for string field class's `encoding` attribute.");
2680 if (strcmp(s_right
, "UTF8") == 0 || strcmp(s_right
, "utf8") == 0 ||
2681 strcmp(s_right
, "utf-8") == 0 || strcmp(s_right
, "UTF-8") == 0 ||
2682 strcmp(s_right
, "ASCII") == 0 || strcmp(s_right
, "ascii") == 0) {
2683 encoding
= CTF_ENCODING_UTF8
;
2684 } else if (strcmp(s_right
, "none") == 0) {
2685 encoding
= CTF_ENCODING_NONE
;
2687 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2689 "Invalid `encoding` attribute in string field class: "
2690 "unknown encoding: encoding=\"%s\"",
2698 _SET(&set
, _STRING_ENCODING_SET
);
2700 _BT_COMP_LOGW_NODE(left
,
2701 "Unknown attribute in string field class: "
2703 left
->u
.unary_expression
.u
.string
);
2707 *string_decl
= ctf_field_class_string_create();
2708 BT_ASSERT(*string_decl
);
2709 (*string_decl
)->encoding
= encoding
;
2713 ctf_field_class_destroy(&(*string_decl
)->base
);
2714 *string_decl
= NULL
;
2718 static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir
*ctx
,
2719 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
)
2722 struct ctf_node
*first
, *node
;
2726 if (ts_list
->type
!= NODE_TYPE_SPECIFIER_LIST
) {
2727 _BT_COMP_LOGE_APPEND_CAUSE_NODE(ts_list
, "Unexpected node type: node-type=%d",
2733 first
= _BT_LIST_FIRST_ENTRY(&ts_list
->u
.field_class_specifier_list
.head
, struct ctf_node
,
2735 if (first
->type
!= NODE_TYPE_SPECIFIER
) {
2736 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Unexpected node type: node-type=%d", first
->type
);
2741 node
= first
->u
.field_class_specifier
.node
;
2743 switch (first
->u
.field_class_specifier
.type
) {
2744 case TYPESPEC_INTEGER
:
2746 ctf_field_class_int
*int_decl
;
2748 ret
= visit_integer_decl(ctx
, &node
->u
.integer
.expressions
, &int_decl
);
2750 BT_ASSERT(!int_decl
);
2754 *decl
= &int_decl
->base
.base
;
2757 case TYPESPEC_FLOATING_POINT
:
2759 ctf_field_class_float
*float_decl
;
2762 visit_floating_point_number_decl(ctx
, &node
->u
.floating_point
.expressions
, &float_decl
);
2764 BT_ASSERT(!float_decl
);
2768 *decl
= &float_decl
->base
.base
;
2771 case TYPESPEC_STRING
:
2773 ctf_field_class_string
*string_decl
;
2775 ret
= visit_string_decl(ctx
, &node
->u
.string
.expressions
, &string_decl
);
2777 BT_ASSERT(!string_decl
);
2781 *decl
= &string_decl
->base
;
2784 case TYPESPEC_STRUCT
:
2786 ctf_field_class_struct
*struct_decl
;
2788 ret
= visit_struct_decl(ctx
, node
->u
._struct
.name
, &node
->u
._struct
.declaration_list
,
2789 node
->u
._struct
.has_body
, &node
->u
._struct
.min_align
, &struct_decl
);
2791 BT_ASSERT(!struct_decl
);
2795 *decl
= &struct_decl
->base
;
2798 case TYPESPEC_VARIANT
:
2800 ctf_field_class_variant
*variant_decl
;
2802 ret
= visit_variant_decl(ctx
, node
->u
.variant
.name
, node
->u
.variant
.choice
,
2803 &node
->u
.variant
.declaration_list
, node
->u
.variant
.has_body
,
2806 BT_ASSERT(!variant_decl
);
2810 *decl
= &variant_decl
->base
;
2815 ctf_field_class_enum
*enum_decl
;
2817 ret
= visit_enum_decl(ctx
, node
->u
._enum
.enum_id
, node
->u
._enum
.container_field_class
,
2818 &node
->u
._enum
.enumerator_list
, node
->u
._enum
.has_body
, &enum_decl
);
2820 BT_ASSERT(!enum_decl
);
2824 *decl
= &enum_decl
->base
.base
.base
;
2829 case TYPESPEC_SHORT
:
2832 case TYPESPEC_FLOAT
:
2833 case TYPESPEC_DOUBLE
:
2834 case TYPESPEC_SIGNED
:
2835 case TYPESPEC_UNSIGNED
:
2837 case TYPESPEC_COMPLEX
:
2838 case TYPESPEC_IMAGINARY
:
2839 case TYPESPEC_CONST
:
2840 case TYPESPEC_ID_TYPE
:
2841 ret
= visit_field_class_specifier(ctx
, ts_list
, decl
);
2843 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
, "Cannot visit field class specifier: ret=%d",
2850 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
,
2851 "Unexpected field class specifier type: node-type=%d",
2852 first
->u
.field_class_specifier
.type
);
2861 ctf_field_class_destroy(*decl
);
2866 static int visit_event_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
2867 struct ctf_event_class
*event_class
, uint64_t *stream_id
,
2873 switch (node
->type
) {
2875 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
2876 &node
->u
.field_class_def
.field_class_declarators
);
2878 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in event class.");
2882 case NODE_TYPEALIAS
:
2883 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
2884 node
->u
.field_class_alias
.alias
);
2886 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2887 "Cannot add field class alias found in event class.");
2891 case NODE_CTF_EXPRESSION
:
2893 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
2895 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
2900 if (strcmp(left
, "name") == 0) {
2901 /* This is already known at this stage */
2902 if (_IS_SET(set
, _EVENT_NAME_SET
)) {
2903 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "name", "event class");
2908 _SET(set
, _EVENT_NAME_SET
);
2909 } else if (strcmp(left
, "id") == 0) {
2912 if (_IS_SET(set
, _EVENT_ID_SET
)) {
2913 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "event class");
2918 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
2919 /* Only read "id" if get_unary_unsigned() succeeded. */
2920 if (ret
|| (!ret
&& id
< 0)) {
2921 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2922 node
, "Unexpected unary expression for event class's `id` attribute.");
2927 event_class
->id
= id
;
2928 _SET(set
, _EVENT_ID_SET
);
2929 } else if (strcmp(left
, "stream_id") == 0) {
2930 if (_IS_SET(set
, _EVENT_STREAM_ID_SET
)) {
2931 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "stream_id", "event class");
2936 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, stream_id
);
2939 * Only read "stream_id" if get_unary_unsigned()
2943 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2944 node
, "Unexpected unary expression for event class's `stream_id` attribute.");
2949 _SET(set
, _EVENT_STREAM_ID_SET
);
2950 } else if (strcmp(left
, "context") == 0) {
2951 if (_IS_SET(set
, _EVENT_CONTEXT_SET
)) {
2952 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `context` entry in event class.");
2957 ret
= visit_field_class_specifier_list(
2958 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2959 &event_class
->spec_context_fc
);
2961 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2962 "Cannot create event class's context field class.");
2966 BT_ASSERT(event_class
->spec_context_fc
);
2967 _SET(set
, _EVENT_CONTEXT_SET
);
2968 } else if (strcmp(left
, "fields") == 0) {
2969 if (_IS_SET(set
, _EVENT_FIELDS_SET
)) {
2970 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `fields` entry in event class.");
2975 ret
= visit_field_class_specifier_list(
2976 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
2977 &event_class
->payload_fc
);
2979 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2980 "Cannot create event class's payload field class.");
2984 BT_ASSERT(event_class
->payload_fc
);
2985 _SET(set
, _EVENT_FIELDS_SET
);
2986 } else if (strcmp(left
, "loglevel") == 0) {
2987 uint64_t loglevel_value
;
2988 bool is_log_level_known
= true;
2989 bt_event_class_log_level log_level
;
2991 if (_IS_SET(set
, _EVENT_LOG_LEVEL_SET
)) {
2992 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "loglevel", "event class");
2997 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &loglevel_value
);
2999 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3000 node
, "Unexpected unary expression for event class's `loglevel` attribute.");
3005 switch (loglevel_value
) {
3007 log_level
= BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
;
3010 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ALERT
;
3013 log_level
= BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
;
3016 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ERROR
;
3019 log_level
= BT_EVENT_CLASS_LOG_LEVEL_WARNING
;
3022 log_level
= BT_EVENT_CLASS_LOG_LEVEL_NOTICE
;
3025 log_level
= BT_EVENT_CLASS_LOG_LEVEL_INFO
;
3028 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
;
3031 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
;
3034 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
;
3037 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
;
3040 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
;
3043 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
;
3046 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
;
3049 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG
;
3052 is_log_level_known
= false;
3055 "Not setting event class's log level because its value is unknown: "
3056 "log-level=%" PRIu64
,
3060 if (is_log_level_known
) {
3061 ctf_event_class_set_log_level(event_class
, log_level
);
3064 _SET(set
, _EVENT_LOG_LEVEL_SET
);
3065 } else if (strcmp(left
, "model.emf.uri") == 0) {
3068 if (_IS_SET(set
, _EVENT_MODEL_EMF_URI_SET
)) {
3069 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "model.emf.uri", "event class");
3074 right
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.right
);
3076 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3078 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3083 if (strlen(right
) == 0) {
3084 _BT_COMP_LOGW_NODE(node
, "Not setting event class's EMF URI because it's empty.");
3086 g_string_assign(event_class
->emf_uri
, right
);
3090 _SET(set
, _EVENT_MODEL_EMF_URI_SET
);
3092 _BT_COMP_LOGW_NODE(node
,
3093 "Unknown attribute in event class: "
3116 static char *get_event_decl_name(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3120 struct ctf_node
*iter
;
3121 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3123 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3124 if (iter
->type
!= NODE_CTF_EXPRESSION
) {
3128 left
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.left
);
3130 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot concatenate unary strings.");
3134 if (strcmp(left
, "name") == 0) {
3135 name
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.right
);
3137 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3138 iter
, "Unexpected unary expression for event class's `name` attribute.");
3158 static int visit_event_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3162 struct ctf_node
*iter
;
3163 uint64_t stream_id
= 0;
3164 char *event_name
= NULL
;
3165 struct ctf_event_class
*event_class
= NULL
;
3166 struct ctf_stream_class
*stream_class
= NULL
;
3167 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3168 bool pop_scope
= false;
3170 if (node
->visited
) {
3174 node
->visited
= TRUE
;
3175 event_name
= get_event_decl_name(ctx
, node
);
3177 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `name` attribute in event class.");
3182 event_class
= ctf_event_class_create();
3183 BT_ASSERT(event_class
);
3184 g_string_assign(event_class
->name
, event_name
);
3185 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3188 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3189 ret
= visit_event_decl_entry(ctx
, iter
, event_class
, &stream_id
, &set
);
3191 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3192 "Cannot visit event class's entry: "
3199 if (!_IS_SET(&set
, _EVENT_STREAM_ID_SET
)) {
3201 * Allow missing stream_id if there is only a single
3204 switch (ctx
->ctf_tc
->stream_classes
->len
) {
3206 /* Create implicit stream class if there's none */
3208 stream_class
= ctf_stream_class_create();
3209 BT_ASSERT(stream_class
);
3210 stream_class
->id
= stream_id
;
3211 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3214 /* Single stream class: get its ID */
3215 stream_class
= (ctf_stream_class
*) ctx
->ctf_tc
->stream_classes
->pdata
[0];
3216 stream_id
= stream_class
->id
;
3219 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `stream_id` attribute in event class.");
3225 /* We have the stream ID now; get the stream class if found */
3226 if (!stream_class
) {
3227 stream_class
= ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_id
);
3228 if (!stream_class
) {
3229 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3230 "Cannot find stream class at this point: "
3238 BT_ASSERT(stream_class
);
3240 if (!_IS_SET(&set
, _EVENT_ID_SET
)) {
3241 /* Allow only one event without ID per stream */
3242 if (stream_class
->event_classes
->len
!= 0) {
3243 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Missing `id` attribute in event class.");
3249 event_class
->id
= 0;
3252 if (ctf_stream_class_borrow_event_class_by_id(stream_class
, event_class
->id
)) {
3253 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3254 "Duplicate event class (same ID) in the same stream class: "
3261 ctf_stream_class_append_event_class(stream_class
, event_class
);
3266 ctf_event_class_destroy(event_class
);
3283 static int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3284 struct ctf_field_class
*fc
)
3286 struct ctf_clock_class
*clock_class_to_map_to
= NULL
;
3287 uint64_t clock_class_count
;
3293 if (fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&& fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3297 ctf_field_class_int
*int_fc
= ctf_field_class_as_int(fc
);
3299 if (int_fc
->mapped_clock_class
) {
3300 /* Already mapped */
3304 clock_class_count
= ctx
->ctf_tc
->clock_classes
->len
;
3306 switch (clock_class_count
) {
3309 * No clock class exists in the trace at this point. Create an
3310 * implicit one at 1 GHz, named `default`, and use this clock
3313 clock_class_to_map_to
= ctf_clock_class_create();
3314 BT_ASSERT(clock_class_to_map_to
);
3315 clock_class_to_map_to
->frequency
= UINT64_C(1000000000);
3316 g_string_assign(clock_class_to_map_to
->name
, "default");
3317 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock_class_to_map_to
);
3321 * Only one clock class exists in the trace at this point: use
3324 clock_class_to_map_to
= (ctf_clock_class
*) ctx
->ctf_tc
->clock_classes
->pdata
[0];
3328 * Timestamp field not mapped to a clock class and there's more
3329 * than one clock class in the trace: this is an error.
3331 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3332 "Timestamp field found with no mapped clock class, "
3333 "but there's more than one clock class in the trace at this point.");
3337 BT_ASSERT(clock_class_to_map_to
);
3338 int_fc
->mapped_clock_class
= clock_class_to_map_to
;
3343 static int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir
*ctx
,
3344 struct ctf_field_class
*root_fc
,
3345 const char *field_name
)
3349 struct ctf_field_class_struct
*struct_fc
= (ctf_field_class_struct
*) root_fc
;
3350 struct ctf_field_class_variant
*var_fc
= (ctf_field_class_variant
*) root_fc
;
3356 if (root_fc
->type
!= CTF_FIELD_CLASS_TYPE_STRUCT
&&
3357 root_fc
->type
!= CTF_FIELD_CLASS_TYPE_VARIANT
) {
3361 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3362 count
= struct_fc
->members
->len
;
3364 count
= var_fc
->options
->len
;
3367 for (i
= 0; i
< count
; i
++) {
3368 struct ctf_named_field_class
*named_fc
= NULL
;
3370 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3371 named_fc
= ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
3372 } else if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
3373 named_fc
= ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
3378 if (strcmp(named_fc
->name
->str
, field_name
) == 0) {
3379 ret
= auto_map_field_to_trace_clock_class(ctx
, named_fc
->fc
);
3381 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3382 "Cannot automatically map field to trace's clock class: "
3383 "field-name=\"%s\"",
3389 ret
= auto_map_fields_to_trace_clock_class(ctx
, named_fc
->fc
, field_name
);
3391 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3392 "Cannot automatically map structure or variant field class's fields to trace's clock class: "
3393 "field-name=\"%s\", root-field-name=\"%s\"",
3394 field_name
, named_fc
->name
->str
);
3403 static int visit_stream_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3404 struct ctf_stream_class
*stream_class
, int *set
)
3409 switch (node
->type
) {
3411 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3412 &node
->u
.field_class_def
.field_class_declarators
);
3414 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot add field class found in stream class.");
3418 case NODE_TYPEALIAS
:
3419 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3420 node
->u
.field_class_alias
.alias
);
3422 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3423 "Cannot add field class alias found in stream class.");
3427 case NODE_CTF_EXPRESSION
:
3429 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3431 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3436 if (strcmp(left
, "id") == 0) {
3439 if (_IS_SET(set
, _STREAM_ID_SET
)) {
3440 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "stream declaration");
3445 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, (uint64_t *) &id
);
3447 /* Only read "id" if get_unary_unsigned() succeeded. */
3448 if (ret
|| (!ret
&& id
< 0)) {
3449 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3450 node
, "Unexpected unary expression for stream class's `id` attribute.");
3455 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, id
)) {
3456 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3457 node
, "Duplicate stream class (same ID): id=%" PRId64
, id
);
3462 stream_class
->id
= id
;
3463 _SET(set
, _STREAM_ID_SET
);
3464 } else if (strcmp(left
, "event.header") == 0) {
3465 if (_IS_SET(set
, _STREAM_EVENT_HEADER_SET
)) {
3466 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3467 "Duplicate `event.header` entry in stream class.");
3472 ret
= visit_field_class_specifier_list(
3473 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3474 &stream_class
->event_header_fc
);
3476 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3477 node
, "Cannot create stream class's event header field class.");
3481 BT_ASSERT(stream_class
->event_header_fc
);
3482 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->event_header_fc
,
3485 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3487 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3491 _SET(set
, _STREAM_EVENT_HEADER_SET
);
3492 } else if (strcmp(left
, "event.context") == 0) {
3493 if (_IS_SET(set
, _STREAM_EVENT_CONTEXT_SET
)) {
3494 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3495 "Duplicate `event.context` entry in stream class.");
3500 ret
= visit_field_class_specifier_list(
3501 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3502 &stream_class
->event_common_context_fc
);
3504 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3505 node
, "Cannot create stream class's event context field class.");
3509 BT_ASSERT(stream_class
->event_common_context_fc
);
3510 _SET(set
, _STREAM_EVENT_CONTEXT_SET
);
3511 } else if (strcmp(left
, "packet.context") == 0) {
3512 if (_IS_SET(set
, _STREAM_PACKET_CONTEXT_SET
)) {
3513 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3514 node
, "Duplicate `packet.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
->packet_context_fc
);
3523 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3524 node
, "Cannot create stream class's packet context field class.");
3528 BT_ASSERT(stream_class
->packet_context_fc
);
3529 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3532 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3534 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3538 ret
= auto_map_fields_to_trace_clock_class(ctx
, stream_class
->packet_context_fc
,
3541 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3543 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3547 _SET(set
, _STREAM_PACKET_CONTEXT_SET
);
3549 _BT_COMP_LOGW_NODE(node
,
3550 "Unknown attribute in stream class: "
3572 static int visit_stream_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3576 struct ctf_node
*iter
;
3577 struct ctf_stream_class
*stream_class
= NULL
;
3578 struct bt_list_head
*decl_list
= &node
->u
.stream
.declaration_list
;
3580 if (node
->visited
) {
3584 node
->visited
= TRUE
;
3585 stream_class
= ctf_stream_class_create();
3586 BT_ASSERT(stream_class
);
3587 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3589 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3590 ret
= visit_stream_decl_entry(ctx
, iter
, stream_class
, &set
);
3592 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3593 "Cannot visit stream class's entry: "
3603 if (_IS_SET(&set
, _STREAM_ID_SET
)) {
3604 /* Check that packet header has `stream_id` field */
3605 struct ctf_named_field_class
*named_fc
= NULL
;
3607 if (!ctx
->ctf_tc
->packet_header_fc
) {
3608 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Stream class has a `id` attribute, "
3609 "but trace has no packet header field class.");
3614 named_fc
= ctf_field_class_struct_borrow_member_by_name(
3615 ctf_field_class_as_struct(ctx
->ctf_tc
->packet_header_fc
), "stream_id");
3617 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3618 node
, "Stream class has a `id` attribute, "
3619 "but trace's packet header field class has no `stream_id` field.");
3624 if (named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3625 named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3626 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3628 "Stream class has a `id` attribute, "
3629 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3634 /* Allow only _one_ ID-less stream */
3635 if (ctx
->ctf_tc
->stream_classes
->len
!= 0) {
3636 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3638 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3643 /* Automatic ID: 0 */
3644 stream_class
->id
= 0;
3648 * Make sure that this stream class's ID is currently unique in
3651 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
, stream_class
->id
)) {
3652 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate stream class (same ID): id=%" PRId64
,
3658 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3659 stream_class
= NULL
;
3663 ctf_stream_class_destroy(stream_class
);
3664 stream_class
= NULL
;
3670 static int visit_trace_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
,
3677 switch (node
->type
) {
3679 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3680 &node
->u
.field_class_def
.field_class_declarators
);
3682 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3683 node
, "Cannot add field class found in trace (`trace` block).");
3687 case NODE_TYPEALIAS
:
3688 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3689 node
->u
.field_class_alias
.alias
);
3691 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3692 node
, "Cannot add field class alias found in trace (`trace` block).");
3696 case NODE_CTF_EXPRESSION
:
3698 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3700 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3705 if (strcmp(left
, "major") == 0) {
3706 if (_IS_SET(set
, _TRACE_MAJOR_SET
)) {
3707 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "major", "trace");
3712 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3714 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3715 node
, "Unexpected unary expression for trace's `major` attribute.");
3721 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3722 "Invalid trace's `minor` attribute: expecting 1.");
3727 ctx
->ctf_tc
->major
= val
;
3728 _SET(set
, _TRACE_MAJOR_SET
);
3729 } else if (strcmp(left
, "minor") == 0) {
3730 if (_IS_SET(set
, _TRACE_MINOR_SET
)) {
3731 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "minor", "trace");
3736 ret
= get_unary_unsigned(ctx
, &node
->u
.ctf_expression
.right
, &val
);
3738 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3739 node
, "Unexpected unary expression for trace's `minor` attribute.");
3745 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3746 "Invalid trace's `minor` attribute: expecting 8.");
3751 ctx
->ctf_tc
->minor
= val
;
3752 _SET(set
, _TRACE_MINOR_SET
);
3753 } else if (strcmp(left
, "uuid") == 0) {
3754 if (_IS_SET(set
, _TRACE_UUID_SET
)) {
3755 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "uuid", "trace");
3760 ret
= get_unary_uuid(ctx
, &node
->u
.ctf_expression
.right
, ctx
->ctf_tc
->uuid
);
3762 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid trace's `uuid` attribute.");
3766 ctx
->ctf_tc
->is_uuid_set
= true;
3767 _SET(set
, _TRACE_UUID_SET
);
3768 } else if (strcmp(left
, "byte_order") == 0) {
3769 /* Default byte order is already known at this stage */
3770 if (_IS_SET(set
, _TRACE_BYTE_ORDER_SET
)) {
3771 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
3776 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
!= CTF_BYTE_ORDER_UNKNOWN
);
3777 _SET(set
, _TRACE_BYTE_ORDER_SET
);
3778 } else if (strcmp(left
, "packet.header") == 0) {
3779 if (_IS_SET(set
, _TRACE_PACKET_HEADER_SET
)) {
3780 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate `packet.header` entry in trace.");
3785 ret
= visit_field_class_specifier_list(
3786 ctx
, _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
),
3787 &ctx
->ctf_tc
->packet_header_fc
);
3789 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3790 "Cannot create trace's packet header field class.");
3794 BT_ASSERT(ctx
->ctf_tc
->packet_header_fc
);
3795 _SET(set
, _TRACE_PACKET_HEADER_SET
);
3797 _BT_COMP_LOGW_NODE(node
,
3798 "Unknown attribute in stream class: "
3808 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unknown expression in trace.");
3820 static int visit_trace_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3824 struct ctf_node
*iter
;
3825 struct bt_list_head
*decl_list
= &node
->u
.trace
.declaration_list
;
3827 if (node
->visited
) {
3831 node
->visited
= TRUE
;
3833 if (ctx
->is_trace_visited
) {
3834 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
3839 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3841 bt_list_for_each_entry (iter
, decl_list
, siblings
) {
3842 ret
= visit_trace_decl_entry(ctx
, iter
, &set
);
3844 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3845 "Cannot visit trace's entry (`trace` block): "
3855 if (!_IS_SET(&set
, _TRACE_MAJOR_SET
)) {
3856 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3857 "Missing `major` attribute in trace (`trace` block).");
3862 if (!_IS_SET(&set
, _TRACE_MINOR_SET
)) {
3863 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3864 "Missing `minor` attribute in trace (`trace` block).");
3869 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
3870 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3871 "Missing `byte_order` attribute in trace (`trace` block).");
3876 ctx
->is_trace_visited
= true;
3885 static int visit_env(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
3889 struct ctf_node
*entry_node
;
3890 struct bt_list_head
*decl_list
= &node
->u
.env
.declaration_list
;
3892 if (node
->visited
) {
3896 node
->visited
= TRUE
;
3898 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
3899 struct bt_list_head
*right_head
= &entry_node
->u
.ctf_expression
.right
;
3901 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
3902 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
3903 "Wrong expression in environment entry: "
3910 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
3912 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot get environment entry's name.");
3917 if (is_unary_string(right_head
)) {
3918 char *right
= ctf_ast_concatenate_unary_strings(right_head
);
3921 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3923 "Unexpected unary expression for environment entry's value: "
3930 if (strcmp(left
, "tracer_name") == 0) {
3931 if (strncmp(right
, "lttng", 5) == 0) {
3932 BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: "
3933 "tracer-name=\"%s\"",
3935 ctx
->is_lttng
= true;
3939 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
,
3942 } else if (is_unary_unsigned(right_head
) || is_unary_signed(right_head
)) {
3945 if (is_unary_unsigned(right_head
)) {
3946 ret
= get_unary_unsigned(ctx
, right_head
, (uint64_t *) &v
);
3948 ret
= get_unary_signed(right_head
, &v
);
3951 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3953 "Unexpected unary expression for environment entry's value: "
3960 ctf_trace_class_append_env_entry(ctx
->ctf_tc
, left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
,
3963 _BT_COMP_LOGW_NODE(entry_node
,
3964 "Environment entry has unknown type: "
3981 static int set_trace_byte_order(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*trace_node
)
3986 struct ctf_node
*node
;
3987 struct bt_list_head
*decl_list
= &trace_node
->u
.trace
.declaration_list
;
3989 bt_list_for_each_entry (node
, decl_list
, siblings
) {
3990 if (node
->type
== NODE_CTF_EXPRESSION
) {
3991 struct ctf_node
*right_node
;
3993 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3995 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
4000 if (strcmp(left
, "byte_order") == 0) {
4001 enum ctf_byte_order bo
;
4003 if (_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4004 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order", "trace");
4009 _SET(&set
, _TRACE_BYTE_ORDER_SET
);
4011 _BT_LIST_FIRST_ENTRY(&node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4012 bo
= byte_order_from_unary_expr(ctx
, right_node
);
4013 if (bo
== CTF_BYTE_ORDER_UNKNOWN
) {
4014 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4015 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4016 "expecting `le`, `be`, or `network`.");
4019 } else if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
4020 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4021 node
, "Invalid `byte_order` attribute in trace (`trace` block): "
4022 "cannot be set to `native` here.");
4027 ctx
->ctf_tc
->default_byte_order
= bo
;
4035 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4036 _BT_COMP_LOGE_APPEND_CAUSE_NODE(trace_node
,
4037 "Missing `byte_order` attribute in trace (`trace` block).");
4049 static int visit_clock_decl_entry(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*entry_node
,
4050 struct ctf_clock_class
*clock
, int *set
, int64_t *offset_seconds
,
4051 uint64_t *offset_cycles
)
4056 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4057 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Unexpected node type: node-type=%d",
4063 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
4065 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot concatenate unary strings.");
4070 if (strcmp(left
, "name") == 0) {
4073 if (_IS_SET(set
, _CLOCK_NAME_SET
)) {
4074 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "name", "clock class");
4079 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4081 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4082 entry_node
, "Unexpected unary expression for clock class's `name` attribute.");
4087 g_string_assign(clock
->name
, right
);
4089 _SET(set
, _CLOCK_NAME_SET
);
4090 } else if (strcmp(left
, "uuid") == 0) {
4093 if (_IS_SET(set
, _CLOCK_UUID_SET
)) {
4094 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "uuid", "clock class");
4099 ret
= get_unary_uuid(ctx
, &entry_node
->u
.ctf_expression
.right
, uuid
);
4101 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Invalid clock class's `uuid` attribute.");
4105 clock
->has_uuid
= true;
4106 bt_uuid_copy(clock
->uuid
, uuid
);
4107 _SET(set
, _CLOCK_UUID_SET
);
4108 } else if (strcmp(left
, "description") == 0) {
4111 if (_IS_SET(set
, _CLOCK_DESCRIPTION_SET
)) {
4112 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "description", "clock class");
4117 right
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.right
);
4119 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4121 "Unexpected unary expression for clock class's `description` attribute.");
4126 g_string_assign(clock
->description
, right
);
4128 _SET(set
, _CLOCK_DESCRIPTION_SET
);
4129 } else if (strcmp(left
, "freq") == 0) {
4130 uint64_t freq
= UINT64_C(-1);
4132 if (_IS_SET(set
, _CLOCK_FREQ_SET
)) {
4133 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "freq", "clock class");
4138 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &freq
);
4140 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4141 entry_node
, "Unexpected unary expression for clock class's `freq` attribute.");
4146 if (freq
== UINT64_C(-1) || freq
== 0) {
4147 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4148 "Invalid clock class frequency: freq=%" PRIu64
, freq
);
4153 clock
->frequency
= freq
;
4154 _SET(set
, _CLOCK_FREQ_SET
);
4155 } else if (strcmp(left
, "precision") == 0) {
4158 if (_IS_SET(set
, _CLOCK_PRECISION_SET
)) {
4159 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "precision", "clock class");
4164 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, &precision
);
4166 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4167 entry_node
, "Unexpected unary expression for clock class's `precision` attribute.");
4172 clock
->precision
= precision
;
4173 _SET(set
, _CLOCK_PRECISION_SET
);
4174 } else if (strcmp(left
, "offset_s") == 0) {
4175 if (_IS_SET(set
, _CLOCK_OFFSET_S_SET
)) {
4176 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset_s", "clock class");
4181 ret
= get_unary_signed(&entry_node
->u
.ctf_expression
.right
, offset_seconds
);
4183 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4184 entry_node
, "Unexpected unary expression for clock class's `offset_s` attribute.");
4189 _SET(set
, _CLOCK_OFFSET_S_SET
);
4190 } else if (strcmp(left
, "offset") == 0) {
4191 if (_IS_SET(set
, _CLOCK_OFFSET_SET
)) {
4192 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "offset", "clock class");
4197 ret
= get_unary_unsigned(ctx
, &entry_node
->u
.ctf_expression
.right
, offset_cycles
);
4199 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4200 entry_node
, "Unexpected unary expression for clock class's `offset` attribute.");
4205 _SET(set
, _CLOCK_OFFSET_SET
);
4206 } else if (strcmp(left
, "absolute") == 0) {
4207 struct ctf_node
*right
;
4209 if (_IS_SET(set
, _CLOCK_ABSOLUTE_SET
)) {
4210 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "absolute", "clock class");
4216 _BT_LIST_FIRST_ENTRY(&entry_node
->u
.ctf_expression
.right
, struct ctf_node
, siblings
);
4217 ret
= get_boolean(ctx
, right
);
4219 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4220 entry_node
, "Unexpected unary expression for clock class's `absolute` attribute.");
4225 clock
->is_absolute
= ret
;
4226 _SET(set
, _CLOCK_ABSOLUTE_SET
);
4228 _BT_COMP_LOGW_NODE(entry_node
, "Unknown attribute in clock class: attr-name=\"%s\"", left
);
4240 static inline uint64_t cycles_from_ns(uint64_t frequency
, uint64_t ns
)
4245 if (frequency
== UINT64_C(1000000000)) {
4248 cycles
= (uint64_t) (((double) ns
* (double) frequency
) / 1e9
);
4254 static void calibrate_clock_class_offsets(int64_t *offset_seconds
, uint64_t *offset_cycles
,
4257 if (*offset_cycles
>= freq
) {
4258 const uint64_t s_in_offset_cycles
= *offset_cycles
/ freq
;
4260 *offset_seconds
+= (int64_t) s_in_offset_cycles
;
4261 *offset_cycles
-= (s_in_offset_cycles
* freq
);
4265 static void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir
*ctx
,
4266 struct ctf_clock_class
*clock
)
4268 if (ctx
->decoder_config
.force_clock_class_origin_unix_epoch
) {
4269 clock
->is_absolute
= true;
4275 static void apply_clock_class_offset(struct ctf_visitor_generate_ir
*ctx
,
4276 struct ctf_clock_class
*clock
)
4279 int64_t offset_s_to_apply
= ctx
->decoder_config
.clock_class_offset_s
;
4280 uint64_t offset_ns_to_apply
;
4281 int64_t cur_offset_s
;
4282 uint64_t cur_offset_cycles
;
4284 if (ctx
->decoder_config
.clock_class_offset_s
== 0 &&
4285 ctx
->decoder_config
.clock_class_offset_ns
== 0) {
4289 /* Transfer nanoseconds to seconds as much as possible */
4290 if (ctx
->decoder_config
.clock_class_offset_ns
< 0) {
4291 const int64_t abs_ns
= -ctx
->decoder_config
.clock_class_offset_ns
;
4292 const int64_t abs_extra_s
= abs_ns
/ INT64_C(1000000000) + 1;
4293 const int64_t extra_s
= -abs_extra_s
;
4294 const int64_t offset_ns
=
4295 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4297 BT_ASSERT(offset_ns
> 0);
4298 offset_ns_to_apply
= (uint64_t) offset_ns
;
4299 offset_s_to_apply
+= extra_s
;
4301 const int64_t extra_s
= ctx
->decoder_config
.clock_class_offset_ns
/ INT64_C(1000000000);
4302 const int64_t offset_ns
=
4303 ctx
->decoder_config
.clock_class_offset_ns
- (extra_s
* INT64_C(1000000000));
4305 BT_ASSERT(offset_ns
>= 0);
4306 offset_ns_to_apply
= (uint64_t) offset_ns
;
4307 offset_s_to_apply
+= extra_s
;
4310 freq
= clock
->frequency
;
4311 cur_offset_s
= clock
->offset_seconds
;
4312 cur_offset_cycles
= clock
->offset_cycles
;
4315 cur_offset_s
+= offset_s_to_apply
;
4316 cur_offset_cycles
+= cycles_from_ns(freq
, offset_ns_to_apply
);
4319 * Recalibrate offsets because the part in cycles can be greater
4320 * than the frequency at this point.
4322 calibrate_clock_class_offsets(&cur_offset_s
, &cur_offset_cycles
, freq
);
4324 /* Set final offsets */
4325 clock
->offset_seconds
= cur_offset_s
;
4326 clock
->offset_cycles
= cur_offset_cycles
;
4332 static int visit_clock_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*clock_node
)
4336 struct ctf_clock_class
*clock
;
4337 struct ctf_node
*entry_node
;
4338 struct bt_list_head
*decl_list
= &clock_node
->u
.clock
.declaration_list
;
4339 const char *clock_class_name
;
4340 int64_t offset_seconds
= 0;
4341 uint64_t offset_cycles
= 0;
4344 if (clock_node
->visited
) {
4348 clock_node
->visited
= TRUE
;
4350 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4351 clock
= ctf_clock_class_create();
4353 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
, "Cannot create default clock class.");
4358 bt_list_for_each_entry (entry_node
, decl_list
, siblings
) {
4359 ret
= visit_clock_decl_entry(ctx
, entry_node
, clock
, &set
, &offset_seconds
, &offset_cycles
);
4361 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot visit clock class's entry: ret=%d",
4367 if (!_IS_SET(&set
, _CLOCK_NAME_SET
)) {
4368 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
, "Missing `name` attribute in clock class.");
4373 clock_class_name
= clock
->name
->str
;
4374 BT_ASSERT(clock_class_name
);
4375 if (ctx
->is_lttng
&& strcmp(clock_class_name
, "monotonic") == 0) {
4377 * Old versions of LTTng forgot to set its clock class
4378 * as absolute, even if it is. This is important because
4379 * it's a condition to be able to sort messages
4380 * from different sources.
4382 clock
->is_absolute
= true;
4386 * Adjust offsets so that the part in cycles is less than the
4387 * frequency (move to the part in seconds).
4389 freq
= clock
->frequency
;
4390 calibrate_clock_class_offsets(&offset_seconds
, &offset_cycles
, freq
);
4391 BT_ASSERT(offset_cycles
< clock
->frequency
);
4392 clock
->offset_seconds
= offset_seconds
;
4393 clock
->offset_cycles
= offset_cycles
;
4394 apply_clock_class_offset(ctx
, clock
);
4395 apply_clock_class_is_absolute(ctx
, clock
);
4396 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock
);
4401 ctf_clock_class_destroy(clock
);
4407 static int visit_root_decl(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*root_decl_node
)
4411 if (root_decl_node
->visited
) {
4415 root_decl_node
->visited
= TRUE
;
4417 switch (root_decl_node
->type
) {
4420 visit_field_class_def(ctx
, root_decl_node
->u
.field_class_def
.field_class_specifier_list
,
4421 &root_decl_node
->u
.field_class_def
.field_class_declarators
);
4423 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4424 "Cannot add field class found in root scope.");
4428 case NODE_TYPEALIAS
:
4429 ret
= visit_field_class_alias(ctx
, root_decl_node
->u
.field_class_alias
.target
,
4430 root_decl_node
->u
.field_class_alias
.alias
);
4432 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4433 "Cannot add field class alias found in root scope.");
4437 case NODE_TYPE_SPECIFIER_LIST
:
4439 struct ctf_field_class
*decl
= NULL
;
4442 * Just add the field class specifier to the root
4443 * declaration scope. Put local reference.
4445 ret
= visit_field_class_specifier_list(ctx
, root_decl_node
, &decl
);
4447 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4448 "Cannot visit root scope's field class: "
4455 ctf_field_class_destroy(decl
);
4460 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
, "Unexpected node type: node-type=%d",
4461 root_decl_node
->type
);
4470 struct ctf_visitor_generate_ir
*
4471 ctf_visitor_generate_ir_create(const struct ctf_metadata_decoder_config
*decoder_config
)
4473 struct ctf_visitor_generate_ir
*ctx
= NULL
;
4475 /* Create visitor's context */
4476 ctx
= ctx_create(decoder_config
);
4478 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
, decoder_config
->self_comp
,
4479 "Cannot create visitor's context.");
4493 void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir
*visitor
)
4495 ctx_destroy(visitor
);
4498 bt_trace_class
*ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4502 if (ctx
->trace_class
) {
4503 bt_trace_class_get_ref(ctx
->trace_class
);
4506 return ctx
->trace_class
;
4509 struct ctf_trace_class
*
4510 ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir
*ctx
)
4513 BT_ASSERT_DBG(ctx
->ctf_tc
);
4517 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir
*ctx
, struct ctf_node
*node
)
4521 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
4523 switch (node
->type
) {
4526 struct ctf_node
*iter
;
4527 bool got_trace_decl
= false;
4530 * The first thing we need is the native byte order of
4531 * the trace block, because early class aliases can have
4532 * a `byte_order` attribute set to `native`. If we don't
4533 * have the native byte order yet, and we don't have any
4534 * trace block yet, then fail with EINCOMPLETE.
4536 if (ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_UNKNOWN
) {
4537 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4538 if (got_trace_decl
) {
4539 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
4544 ret
= set_trace_byte_order(ctx
, iter
);
4546 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4547 "Cannot set trace's native byte order: "
4553 got_trace_decl
= true;
4556 if (!got_trace_decl
) {
4557 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
4563 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_LITTLE
||
4564 ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_BIG
);
4565 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4568 bt_list_for_each_entry (iter
, &node
->u
.root
.env
, siblings
) {
4569 ret
= visit_env(ctx
, iter
);
4571 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4573 "Cannot visit trace's environment (`env` block) entry: "
4580 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4583 * Visit clock blocks.
4585 bt_list_for_each_entry (iter
, &node
->u
.root
.clock
, siblings
) {
4586 ret
= visit_clock_decl(ctx
, iter
);
4588 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit clock class: ret=%d", ret
);
4593 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4596 * Visit root declarations next, as they can be used by any
4599 bt_list_for_each_entry (iter
, &node
->u
.root
.declaration_list
, siblings
) {
4600 ret
= visit_root_decl(ctx
, iter
);
4602 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit root entry: ret=%d", ret
);
4607 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4609 /* Callsite blocks are not supported */
4610 bt_list_for_each_entry (iter
, &node
->u
.root
.callsite
, siblings
) {
4611 _BT_COMP_LOGW_NODE(iter
, "\"callsite\" blocks are not supported as of this version.");
4614 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4617 bt_list_for_each_entry (iter
, &node
->u
.root
.trace
, siblings
) {
4618 ret
= visit_trace_decl(ctx
, iter
);
4620 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4621 "Cannot visit trace (`trace` block): "
4628 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4631 bt_list_for_each_entry (iter
, &node
->u
.root
.stream
, siblings
) {
4632 ret
= visit_stream_decl(ctx
, iter
);
4634 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit stream class: ret=%d", ret
);
4639 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4642 bt_list_for_each_entry (iter
, &node
->u
.root
.event
, siblings
) {
4643 ret
= visit_event_decl(ctx
, iter
);
4645 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit event class: ret=%d", ret
);
4650 BT_ASSERT(ctx
->current_scope
&& !ctx
->current_scope
->parent_scope
);
4654 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected node type: node-type=%d", node
->type
);
4659 /* Update default clock classes */
4660 ret
= ctf_trace_class_update_default_clock_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4666 /* Update trace class meanings */
4667 ret
= ctf_trace_class_update_meanings(ctx
->ctf_tc
);
4673 /* Update stream class configuration */
4674 ret
= ctf_trace_class_update_stream_class_config(ctx
->ctf_tc
);
4680 /* Update text arrays and sequences */
4681 ret
= ctf_trace_class_update_text_array_sequence(ctx
->ctf_tc
);
4687 /* Update structure/array/sequence alignments */
4688 ret
= ctf_trace_class_update_alignments(ctx
->ctf_tc
);
4694 /* Resolve sequence lengths and variant tags */
4695 ret
= ctf_trace_class_resolve_field_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4701 if (ctx
->trace_class
) {
4703 * Update "in IR" for field classes.
4705 * If we have no IR trace class, then we'll have no way
4706 * to create IR fields anyway, so we leave all the
4707 * `in_ir` members false.
4709 ret
= ctf_trace_class_update_in_ir(ctx
->ctf_tc
);
4716 /* Update saved value indexes */
4717 ret
= ctf_trace_class_update_value_storing_indexes(ctx
->ctf_tc
);
4723 /* Validate what we have so far */
4724 ret
= ctf_trace_class_validate(ctx
->ctf_tc
, &ctx
->log_cfg
);
4731 * If there are fields which are not related to the CTF format
4732 * itself in the packet header and in event header field
4733 * classes, warn about it because they are never translated.
4735 ctf_trace_class_warn_meaningless_header_fields(ctx
->ctf_tc
, &ctx
->log_cfg
);
4737 if (ctx
->trace_class
) {
4738 /* Copy new CTF metadata -> new IR metadata */
4739 ret
= ctf_trace_class_translate(ctx
->log_cfg
.self_comp
, ctx
->trace_class
, ctx
->ctf_tc
);