2 * SPDX-License-Identifier: MIT
4 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
14 #include <babeltrace2/babeltrace.h>
16 #define BT_COMP_LOG_SELF_COMP (ctx->self_comp)
17 #define BT_LOG_OUTPUT_LEVEL (ctx->log_level)
18 #define BT_LOG_TAG "PLUGIN/SINK.CTF.FS/TRANSLATE-TRACE-IR-TO-CTF-IR"
19 #include "logging/comp-logging.h"
21 #include "common/assert.h"
22 #include "common/common.h"
23 #include "common/macros.h"
25 #include "fs-sink-ctf-meta.hpp"
26 #include "fs-sink.hpp"
27 #include "translate-trace-ir-to-ctf-ir.hpp"
29 struct field_path_elem
31 uint64_t index_in_parent
;
35 const bt_field_class
*ir_fc
;
38 struct fs_sink_ctf_field_class
*parent_fc
;
43 bt_logging_level log_level
;
44 bt_self_component
*self_comp
;
47 struct fs_sink_ctf_stream_class
*cur_sc
;
50 struct fs_sink_ctf_event_class
*cur_ec
;
52 bt_field_path_scope cur_scope
;
55 * Array of `struct field_path_elem` */
59 static inline struct field_path_elem
*cur_path_stack_at(struct ctx
*ctx
, uint64_t i
)
61 BT_ASSERT(i
< ctx
->cur_path
->len
);
62 return &bt_g_array_index(ctx
->cur_path
, struct field_path_elem
, i
);
65 static inline struct field_path_elem
*cur_path_stack_top(struct ctx
*ctx
)
67 BT_ASSERT(ctx
->cur_path
->len
> 0);
68 return cur_path_stack_at(ctx
, ctx
->cur_path
->len
- 1);
71 static inline bool is_reserved_member_name(const char *name
, const char *reserved_name
)
73 bool is_reserved
= false;
75 if (strcmp(name
, reserved_name
) == 0) {
80 if (name
[0] == '_' && strcmp(&name
[1], reserved_name
) == 0) {
89 static const char *reserved_tsdl_keywords
[] = {
90 "align", "callsite", "const", "char", "clock", "double", "enum",
91 "env", "event", "floating_point", "float", "integer", "int", "long",
92 "short", "signed", "stream", "string", "struct", "trace", "typealias",
93 "typedef", "unsigned", "variant", "void", "_Bool", "_Complex", "_Imaginary",
96 static inline bool ist_valid_identifier(const char *name
)
100 bool ist_valid
= true;
102 /* Make sure the name is not a reserved keyword */
103 for (i
= 0; i
< sizeof(reserved_tsdl_keywords
) / sizeof(*reserved_tsdl_keywords
); i
++) {
104 if (strcmp(name
, reserved_tsdl_keywords
[i
]) == 0) {
110 /* Make sure the name is not an empty string */
111 if (strlen(name
) == 0) {
116 /* Make sure the name starts with a letter or `_` */
117 if (!isalpha((unsigned char) name
[0]) && name
[0] != '_') {
122 /* Make sure the name only contains letters, digits, and `_` */
123 for (at
= name
; *at
!= '\0'; at
++) {
124 if (!isalnum((unsigned char) *at
) && *at
!= '_') {
134 static inline bool must_protect_identifier(const char *name
)
137 bool must_protect
= false;
139 /* Protect a reserved keyword */
140 for (i
= 0; i
< sizeof(reserved_tsdl_keywords
) / sizeof(*reserved_tsdl_keywords
); i
++) {
141 if (strcmp(name
, reserved_tsdl_keywords
[i
]) == 0) {
147 /* Protect an identifier which already starts with `_` */
148 if (name
[0] == '_') {
157 static inline int cur_path_stack_push(struct ctx
*ctx
, uint64_t index_in_parent
, const char *name
,
158 bool force_protect_name
, const bt_field_class
*ir_fc
,
159 struct fs_sink_ctf_field_class
*parent_fc
)
162 struct field_path_elem
*field_path_elem
;
164 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
+ 1);
165 field_path_elem
= cur_path_stack_top(ctx
);
166 field_path_elem
->index_in_parent
= index_in_parent
;
167 field_path_elem
->name
= g_string_new(NULL
);
170 if (force_protect_name
) {
171 g_string_assign(field_path_elem
->name
, "_");
174 g_string_append(field_path_elem
->name
, name
);
176 if (ctx
->cur_scope
== BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
) {
177 if (is_reserved_member_name(name
, "packet_size") ||
178 is_reserved_member_name(name
, "content_size") ||
179 is_reserved_member_name(name
, "timestamp_begin") ||
180 is_reserved_member_name(name
, "timestamp_end") ||
181 is_reserved_member_name(name
, "events_discarded") ||
182 is_reserved_member_name(name
, "packet_seq_num")) {
183 BT_COMP_LOGE("Unsupported reserved TSDL structure field class member "
184 "or variant field class option name: name=\"%s\"",
191 if (!ist_valid_identifier(field_path_elem
->name
->str
)) {
193 BT_COMP_LOGE("Unsupported non-TSDL structure field class member "
194 "or variant field class option name: name=\"%s\"",
195 field_path_elem
->name
->str
);
200 field_path_elem
->ir_fc
= ir_fc
;
201 field_path_elem
->parent_fc
= parent_fc
;
207 static inline void cur_path_stack_pop(struct ctx
*ctx
)
209 struct field_path_elem
*field_path_elem
;
211 BT_ASSERT(ctx
->cur_path
->len
> 0);
212 field_path_elem
= cur_path_stack_top(ctx
);
214 if (field_path_elem
->name
) {
215 g_string_free(field_path_elem
->name
, TRUE
);
216 field_path_elem
->name
= NULL
;
219 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
- 1);
223 * Creates a relative field ref (a single name) from IR field path
224 * `tgt_ir_field_path`.
226 * This function tries to locate the target field class recursively from
227 * the top to the bottom of the context's current path using only the
228 * target field class's own name. This is because many CTF reading tools
229 * do not support a relative field ref with more than one element, for
230 * example `prev_struct.len`.
232 * Returns a negative value if this resolving operation failed.
234 static int create_relative_field_ref(struct ctx
*ctx
, const bt_field_path
*tgt_ir_field_path
,
235 GString
*tgt_field_ref
,
236 struct fs_sink_ctf_field_class
**user_tgt_fc
)
239 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
242 const char *tgt_fc_name
= NULL
;
243 struct field_path_elem
*field_path_elem
;
245 /* Get target field class's name */
246 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
247 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
248 BT_ASSERT(ctx
->cur_sc
);
249 tgt_fc
= ctx
->cur_sc
->packet_context_fc
;
251 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
252 BT_ASSERT(ctx
->cur_sc
);
253 tgt_fc
= ctx
->cur_sc
->event_common_context_fc
;
255 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
256 BT_ASSERT(ctx
->cur_ec
);
257 tgt_fc
= ctx
->cur_ec
->spec_context_fc
;
259 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
260 BT_ASSERT(ctx
->cur_ec
);
261 tgt_fc
= ctx
->cur_ec
->payload_fc
;
269 while (i
< bt_field_path_get_item_count(tgt_ir_field_path
)) {
270 const bt_field_path_item
*fp_item
=
271 bt_field_path_borrow_item_by_index_const(tgt_ir_field_path
, i
);
272 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
277 if (bt_field_path_item_get_type(fp_item
) ==
278 BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT
) {
279 /* Not supported by CTF 1.8 */
284 switch (tgt_fc
->type
) {
285 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
286 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
287 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
288 fs_sink_ctf_field_class_as_struct(tgt_fc
),
289 bt_field_path_item_index_get_index(fp_item
));
291 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
292 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
293 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
294 fs_sink_ctf_field_class_as_variant(tgt_fc
),
295 bt_field_path_item_index_get_index(fp_item
));
297 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
298 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
300 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
301 fs_sink_ctf_field_class_as_array_base(tgt_fc
);
303 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
304 BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
);
305 tgt_fc
= array_base_fc
->elem_fc
;
313 tgt_fc
= named_fc
->fc
;
314 tgt_fc_name
= named_fc
->name
->str
;
320 BT_ASSERT(tgt_fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_INT
);
321 BT_ASSERT(tgt_fc_name
);
323 /* Find target field class having this name in current context */
324 for (si
= ctx
->cur_path
->len
- 1; si
>= 0; si
--) {
325 struct fs_sink_ctf_field_class
*fc
;
326 struct fs_sink_ctf_field_class_struct
*struct_fc
= NULL
;
327 struct fs_sink_ctf_field_class_variant
*var_fc
= NULL
;
328 struct fs_sink_ctf_named_field_class
*named_fc
;
331 field_path_elem
= cur_path_stack_at(ctx
, (uint64_t) si
);
332 fc
= field_path_elem
->parent_fc
;
334 /* Reached stack's bottom */
340 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
341 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
343 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
344 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
347 /* Not supported by TSDL 1.8 */
352 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
353 struct_fc
= fs_sink_ctf_field_class_as_struct(fc
);
354 len
= struct_fc
->members
->len
;
356 var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
357 len
= var_fc
->options
->len
;
360 for (i
= 0; i
< len
; i
++) {
361 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
362 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
364 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
367 if (strcmp(named_fc
->name
->str
, tgt_fc_name
) == 0) {
368 if (named_fc
->fc
== tgt_fc
) {
369 g_string_assign(tgt_field_ref
, tgt_fc_name
);
372 *user_tgt_fc
= tgt_fc
;
376 * Using only the target field
377 * class's name, we're not
378 * reaching the target field
379 * class. This is not supported
395 * Creates an absolute field ref from IR field path `tgt_ir_field_path`.
397 * Returns a negative value if this resolving operation failed.
399 static int create_absolute_field_ref(struct ctx
*ctx
, const bt_field_path
*tgt_ir_field_path
,
400 GString
*tgt_field_ref
,
401 struct fs_sink_ctf_field_class
**user_tgt_fc
)
404 struct fs_sink_ctf_field_class
*fc
= NULL
;
407 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
408 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
409 BT_ASSERT(ctx
->cur_sc
);
410 fc
= ctx
->cur_sc
->packet_context_fc
;
411 g_string_assign(tgt_field_ref
, "stream.packet.context");
413 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
414 BT_ASSERT(ctx
->cur_sc
);
415 fc
= ctx
->cur_sc
->event_common_context_fc
;
416 g_string_assign(tgt_field_ref
, "stream.event.context");
418 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
419 BT_ASSERT(ctx
->cur_ec
);
420 fc
= ctx
->cur_ec
->spec_context_fc
;
421 g_string_assign(tgt_field_ref
, "event.context");
423 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
424 BT_ASSERT(ctx
->cur_ec
);
425 fc
= ctx
->cur_ec
->payload_fc
;
426 g_string_assign(tgt_field_ref
, "event.fields");
434 for (i
= 0; i
< bt_field_path_get_item_count(tgt_ir_field_path
); i
++) {
435 const bt_field_path_item
*fp_item
=
436 bt_field_path_borrow_item_by_index_const(tgt_ir_field_path
, i
);
437 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
439 if (bt_field_path_item_get_type(fp_item
) != BT_FIELD_PATH_ITEM_TYPE_INDEX
) {
440 /* Not supported by TSDL 1.8 */
446 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
447 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
448 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
449 fs_sink_ctf_field_class_as_struct(fc
), bt_field_path_item_index_get_index(fp_item
));
451 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
452 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
453 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
454 fs_sink_ctf_field_class_as_variant(fc
),
455 bt_field_path_item_index_get_index(fp_item
));
462 g_string_append_c(tgt_field_ref
, '.');
463 g_string_append(tgt_field_ref
, named_fc
->name
->str
);
476 * Resolves a target field class located at `tgt_ir_field_path`, writing
477 * the resolved field ref to `tgt_field_ref` and setting
478 * `*create_before` according to whether or not the target field must be
479 * created immediately before (in which case `tgt_field_ref` is
482 static void resolve_field_class(struct ctx
*ctx
, const bt_field_path
*tgt_ir_field_path
,
483 GString
*tgt_field_ref
, bool *create_before
,
484 struct fs_sink_ctf_field_class
**user_tgt_fc
)
487 bt_field_path_scope tgt_scope
;
489 *create_before
= false;
491 if (!tgt_ir_field_path
) {
492 *create_before
= true;
496 tgt_scope
= bt_field_path_get_root_scope(tgt_ir_field_path
);
498 if (tgt_scope
== ctx
->cur_scope
) {
500 * Try, in this order:
502 * 1. Use a relative path, using only the target field
503 * class's name. This is what is the most commonly
504 * supported by popular CTF reading tools.
506 * 2. Use an absolute path. This could fail if there's
507 * an array field class from the current root's field
508 * class to the target field class.
510 * 3. Create the target field class before the
511 * requesting field class (fallback).
513 ret
= create_relative_field_ref(ctx
, tgt_ir_field_path
, tgt_field_ref
, user_tgt_fc
);
515 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
, tgt_field_ref
, user_tgt_fc
);
517 *create_before
= true;
522 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
, tgt_field_ref
, user_tgt_fc
);
524 /* It must always work in previous scopes */
532 static int translate_field_class(struct ctx
*ctx
);
534 static inline void append_to_parent_field_class(struct ctx
*ctx
, struct fs_sink_ctf_field_class
*fc
)
536 struct fs_sink_ctf_field_class
*parent_fc
= cur_path_stack_top(ctx
)->parent_fc
;
538 switch (parent_fc
->type
) {
539 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
540 fs_sink_ctf_field_class_struct_append_member(fs_sink_ctf_field_class_as_struct(parent_fc
),
541 cur_path_stack_top(ctx
)->name
->str
, fc
);
543 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
545 struct fs_sink_ctf_field_class_option
*opt_fc
=
546 fs_sink_ctf_field_class_as_option(parent_fc
);
548 BT_ASSERT(!opt_fc
->content_fc
);
549 opt_fc
->content_fc
= fc
;
550 opt_fc
->base
.alignment
= fc
->alignment
;
553 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
554 fs_sink_ctf_field_class_variant_append_option(fs_sink_ctf_field_class_as_variant(parent_fc
),
555 cur_path_stack_top(ctx
)->name
->str
, fc
);
557 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
558 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
560 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
561 fs_sink_ctf_field_class_as_array_base(parent_fc
);
563 BT_ASSERT(!array_base_fc
->elem_fc
);
564 array_base_fc
->elem_fc
= fc
;
565 array_base_fc
->base
.alignment
= fc
->alignment
;
573 static inline void update_parent_field_class_alignment(struct ctx
*ctx
, unsigned int alignment
)
575 struct fs_sink_ctf_field_class
*parent_fc
= cur_path_stack_top(ctx
)->parent_fc
;
577 switch (parent_fc
->type
) {
578 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
579 fs_sink_ctf_field_class_struct_align_at_least(fs_sink_ctf_field_class_as_struct(parent_fc
),
582 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
583 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
585 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
586 fs_sink_ctf_field_class_as_array_base(parent_fc
);
588 array_base_fc
->base
.alignment
= alignment
;
596 static inline int translate_structure_field_class_members(
597 struct ctx
*ctx
, struct fs_sink_ctf_field_class_struct
*struct_fc
, const bt_field_class
*ir_fc
)
602 for (i
= 0; i
< bt_field_class_structure_get_member_count(ir_fc
); i
++) {
603 const bt_field_class_structure_member
*member
;
605 const bt_field_class
*memb_ir_fc
;
607 member
= bt_field_class_structure_borrow_member_by_index_const(ir_fc
, i
);
608 name
= bt_field_class_structure_member_get_name(member
);
609 memb_ir_fc
= bt_field_class_structure_member_borrow_field_class_const(member
);
610 ret
= cur_path_stack_push(ctx
, i
, name
, true, memb_ir_fc
, &struct_fc
->base
);
612 BT_COMP_LOGE("Cannot translate structure field class member: "
618 ret
= translate_field_class(ctx
);
620 BT_COMP_LOGE("Cannot translate structure field class member: "
626 cur_path_stack_pop(ctx
);
633 static inline int translate_structure_field_class(struct ctx
*ctx
)
636 struct fs_sink_ctf_field_class_struct
*fc
= fs_sink_ctf_field_class_struct_create_empty(
637 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
640 append_to_parent_field_class(ctx
, &fc
->base
);
641 ret
= translate_structure_field_class_members(ctx
, fc
, fc
->base
.ir_fc
);
646 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
653 * This function protects a given variant FC option name (with the `_`
654 * prefix) if required. On success, `name_buf->str` contains the variant
655 * FC option name to use (original option name or protected if
658 * One of the goals of `sink.ctf.fs` is to write a CTF trace which is as
659 * close as possible to an original CTF trace as decoded by
662 * This scenario is valid in CTF 1.8:
674 * Once in trace IR, the enumeration FC mapping names and variant FC
675 * option names are kept as is. For this reason, we don't want to
676 * protect the variant FC option names here (by prepending `_`): this
677 * would make the variant FC option name and the enumeration FC mapping
680 * This scenario is also valid in CTF 1.8:
692 * Once in trace IR, the enumeration FC mapping names are kept as is,
693 * but the `_HELLO` variant FC option name becomes `HELLO` (unprotected
694 * for presentation, as recommended by CTF 1.8). When going back to
695 * TSDL, we need to protect `HELLO` so that it becomes `_HELLO` to match
696 * the corresponding enumeration FC mapping name.
698 * This scenario is also valid in CTF 1.8:
710 * Once in trace IR, the enumeration FC mapping names are kept as is,
711 * but the `__HELLO` variant FC option name becomes `_HELLO`
712 * (unprotected). When going back to TSDL, we need to protect `_HELLO`
713 * so that it becomes `__HELLO` to match the corresponding enumeration
716 * `src.ctf.fs` always uses the _same_ integer range sets for a selector
717 * FC mapping and a corresponding variant FC option. We can use that
718 * fact to find the original variant FC option names by matching variant
719 * FC options and enumeration FC mappings by range set.
721 static int maybe_protect_variant_option_name(const bt_field_class
*ir_var_fc
,
722 const bt_field_class
*ir_tag_fc
, uint64_t opt_i
,
727 bt_field_class_type ir_var_fc_type
;
728 const bt_integer_range_set_unsigned
*opt_ranges_unsigned
= NULL
;
729 const bt_integer_range_set_signed
*opt_ranges_signed
= NULL
;
730 const char *mapping_label
= NULL
;
731 const char *ir_opt_name
;
732 const bt_field_class_variant_option
*base_var_opt
;
733 bool force_protect
= false;
735 ir_var_fc_type
= bt_field_class_get_type(ir_var_fc
);
736 base_var_opt
= bt_field_class_variant_borrow_option_by_index_const(ir_var_fc
, opt_i
);
737 BT_ASSERT(base_var_opt
);
738 ir_opt_name
= bt_field_class_variant_option_get_name(base_var_opt
);
739 BT_ASSERT(ir_opt_name
);
742 * Check if the variant FC option name is required to be
743 * protected (reserved TSDL keyword or starts with `_`). In that
744 * case, the name of the selector FC mapping we find must match
745 * exactly the protected name.
747 force_protect
= must_protect_identifier(ir_opt_name
);
749 g_string_assign(name_buf
, "_");
750 g_string_append(name_buf
, ir_opt_name
);
752 g_string_assign(name_buf
, ir_opt_name
);
755 /* Borrow option's ranges */
756 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD
) {
757 /* No ranges: we're done */
760 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
) {
761 const bt_field_class_variant_with_selector_field_integer_unsigned_option
*var_opt
=
762 bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_index_const(
764 opt_ranges_unsigned
=
765 bt_field_class_variant_with_selector_field_integer_unsigned_option_borrow_ranges_const(
768 const bt_field_class_variant_with_selector_field_integer_signed_option
*var_opt
=
769 bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_index_const(
772 bt_field_class_variant_with_selector_field_integer_signed_option_borrow_ranges_const(
776 /* Find corresponding mapping by range set in selector FC */
777 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(ir_tag_fc
); i
++) {
778 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
) {
779 const bt_field_class_enumeration_mapping
*mapping_base
;
780 const bt_field_class_enumeration_unsigned_mapping
*mapping
;
781 const bt_integer_range_set_unsigned
*mapping_ranges
;
784 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(ir_tag_fc
, i
);
786 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(mapping
);
788 if (bt_integer_range_set_unsigned_is_equal(opt_ranges_unsigned
, mapping_ranges
)) {
789 /* We have a winner */
791 bt_field_class_enumeration_unsigned_mapping_as_mapping_const(mapping
);
792 mapping_label
= bt_field_class_enumeration_mapping_get_label(mapping_base
);
796 const bt_field_class_enumeration_mapping
*mapping_base
;
797 const bt_field_class_enumeration_signed_mapping
*mapping
;
798 const bt_integer_range_set_signed
*mapping_ranges
;
800 mapping
= bt_field_class_enumeration_signed_borrow_mapping_by_index_const(ir_tag_fc
, i
);
801 mapping_ranges
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(mapping
);
803 if (bt_integer_range_set_signed_is_equal(opt_ranges_signed
, mapping_ranges
)) {
804 /* We have a winner */
805 mapping_base
= bt_field_class_enumeration_signed_mapping_as_mapping_const(mapping
);
806 mapping_label
= bt_field_class_enumeration_mapping_get_label(mapping_base
);
812 if (!mapping_label
) {
813 /* Range set not found: invalid selector for CTF 1.8 */
819 * If the enumeration FC mapping name is not the same as the
820 * variant FC option name and we didn't protect already, try
821 * protecting the option name and check again.
823 if (strcmp(mapping_label
, name_buf
->str
) != 0) {
829 if (mapping_label
[0] == '\0') {
834 g_string_assign(name_buf
, "_");
835 g_string_append(name_buf
, ir_opt_name
);
837 if (strcmp(mapping_label
, name_buf
->str
) != 0) {
847 static inline int translate_option_field_class(struct ctx
*ctx
)
849 struct fs_sink_ctf_field_class_option
*fc
= fs_sink_ctf_field_class_option_create_empty(
850 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
851 const bt_field_class
*content_ir_fc
=
852 bt_field_class_option_borrow_field_class_const(fc
->base
.ir_fc
);
858 * CTF 1.8 does not support the option field class type. To
859 * write something anyway, this component translates this type
860 * to a variant field class where the options are:
862 * * An empty structure field class.
863 * * The optional field class itself.
865 * The "tag" is always generated/before in that case (an 8-bit
866 * unsigned enumeration field class).
868 append_to_parent_field_class(ctx
, &fc
->base
);
869 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, content_ir_fc
, &fc
->base
);
871 BT_COMP_LOGE_STR("Cannot translate option field class content.");
875 ret
= translate_field_class(ctx
);
877 BT_COMP_LOGE_STR("Cannot translate option field class content.");
881 cur_path_stack_pop(ctx
);
882 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
888 static inline int translate_variant_field_class(struct ctx
*ctx
)
892 struct fs_sink_ctf_field_class_variant
*fc
= fs_sink_ctf_field_class_variant_create_empty(
893 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
894 bt_field_class_type ir_fc_type
;
895 const bt_field_path
*ir_selector_field_path
= NULL
;
896 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
897 GString
*name_buf
= g_string_new(NULL
);
898 bt_value
*prot_opt_names
= bt_value_array_create();
903 BT_ASSERT(prot_opt_names
);
904 ir_fc_type
= bt_field_class_get_type(fc
->base
.ir_fc
);
905 opt_count
= bt_field_class_variant_get_option_count(fc
->base
.ir_fc
);
907 if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_VARIANT_WITH_SELECTOR_FIELD
)) {
908 ir_selector_field_path
=
909 bt_field_class_variant_with_selector_field_borrow_selector_field_path_const(
911 BT_ASSERT(ir_selector_field_path
);
914 /* Resolve tag field class before appending to parent */
915 resolve_field_class(ctx
, ir_selector_field_path
, fc
->tag_ref
, &fc
->tag_is_before
, &tgt_fc
);
917 if (ir_selector_field_path
&& tgt_fc
) {
918 uint64_t mapping_count
;
919 uint64_t option_count
;
921 /* CTF 1.8: selector FC must be an enumeration FC */
922 bt_field_class_type type
= bt_field_class_get_type(tgt_fc
->ir_fc
);
924 if (!bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
925 fc
->tag_is_before
= true;
930 * Call maybe_protect_variant_option_name() for each
931 * option below. In that case we also want selector FC
932 * to contain as many mappings as the variant FC has
935 mapping_count
= bt_field_class_enumeration_get_mapping_count(tgt_fc
->ir_fc
);
936 option_count
= bt_field_class_variant_get_option_count(fc
->base
.ir_fc
);
938 if (mapping_count
!= option_count
) {
939 fc
->tag_is_before
= true;
944 * No compatible selector field class for CTF 1.8:
945 * create the appropriate selector field class.
947 fc
->tag_is_before
= true;
953 * First pass: detect any option name clash with option name
954 * protection. In that case, we don't fail: just create the
955 * selector field class before the variant field class.
957 * After this, `prot_opt_names` contains the final option names,
958 * potentially protected if needed. They can still be invalid
959 * TSDL identifiers however; this will be checked by
960 * cur_path_stack_push().
962 for (i
= 0; i
< opt_count
; i
++) {
963 if (!fc
->tag_is_before
) {
964 BT_ASSERT(tgt_fc
->ir_fc
);
965 ret
= maybe_protect_variant_option_name(fc
->base
.ir_fc
, tgt_fc
->ir_fc
, i
, name_buf
);
967 fc
->tag_is_before
= true;
971 ret
= bt_value_array_append_string_element(prot_opt_names
, name_buf
->str
);
977 for (i
= 0; i
< opt_count
; i
++) {
979 const bt_value
*opt_name_a
=
980 bt_value_array_borrow_element_by_index_const(prot_opt_names
, i
);
982 for (j
= 0; j
< opt_count
; j
++) {
983 const bt_value
*opt_name_b
;
989 opt_name_b
= bt_value_array_borrow_element_by_index_const(prot_opt_names
, j
);
990 if (bt_value_is_equal(opt_name_a
, opt_name_b
)) {
992 * Variant FC option names are not
993 * unique when protected.
995 fc
->tag_is_before
= true;
996 goto append_to_parent
;
1002 append_to_parent_field_class(ctx
, &fc
->base
);
1004 for (i
= 0; i
< opt_count
; i
++) {
1005 const bt_field_class_variant_option
*opt
;
1006 const bt_field_class
*opt_ir_fc
;
1007 const bt_value
*prot_opt_name_val
=
1008 bt_value_array_borrow_element_by_index_const(prot_opt_names
, i
);
1009 const char *prot_opt_name
= bt_value_string_get(prot_opt_name_val
);
1011 BT_ASSERT(prot_opt_name
);
1012 opt
= bt_field_class_variant_borrow_option_by_index_const(fc
->base
.ir_fc
, i
);
1013 opt_ir_fc
= bt_field_class_variant_option_borrow_field_class_const(opt
);
1016 * We don't ask cur_path_stack_push() to protect the
1017 * option name because it's already protected at this
1020 ret
= cur_path_stack_push(ctx
, i
, prot_opt_name
, false, opt_ir_fc
, &fc
->base
);
1022 BT_COMP_LOGE("Cannot translate variant field class option: "
1028 ret
= translate_field_class(ctx
);
1030 BT_COMP_LOGE("Cannot translate variant field class option: "
1036 cur_path_stack_pop(ctx
);
1041 g_string_free(name_buf
, TRUE
);
1044 bt_value_put_ref(prot_opt_names
);
1048 static inline int translate_static_array_field_class(struct ctx
*ctx
)
1050 struct fs_sink_ctf_field_class_array
*fc
= fs_sink_ctf_field_class_array_create_empty(
1051 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1052 const bt_field_class
*elem_ir_fc
=
1053 bt_field_class_array_borrow_element_field_class_const(fc
->base
.base
.ir_fc
);
1057 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1058 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, elem_ir_fc
, &fc
->base
.base
);
1060 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1064 ret
= translate_field_class(ctx
);
1066 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1070 cur_path_stack_pop(ctx
);
1071 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
1077 static inline int translate_dynamic_array_field_class(struct ctx
*ctx
)
1079 struct fs_sink_ctf_field_class_sequence
*fc
= fs_sink_ctf_field_class_sequence_create_empty(
1080 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1081 const bt_field_class
*elem_ir_fc
=
1082 bt_field_class_array_borrow_element_field_class_const(fc
->base
.base
.ir_fc
);
1087 /* Resolve length field class before appending to parent */
1088 if (bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
) ==
1089 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
) {
1090 resolve_field_class(
1092 bt_field_class_array_dynamic_with_length_field_borrow_length_field_path_const(
1093 fc
->base
.base
.ir_fc
),
1094 fc
->length_ref
, &fc
->length_is_before
, NULL
);
1097 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1098 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, elem_ir_fc
, &fc
->base
.base
);
1100 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1104 ret
= translate_field_class(ctx
);
1106 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1110 cur_path_stack_pop(ctx
);
1111 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
1117 static inline int translate_bool_field_class(struct ctx
*ctx
)
1119 struct fs_sink_ctf_field_class_bool
*fc
= fs_sink_ctf_field_class_bool_create(
1120 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1123 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1127 static inline int translate_bit_array_field_class(struct ctx
*ctx
)
1129 struct fs_sink_ctf_field_class_bit_array
*fc
= fs_sink_ctf_field_class_bit_array_create(
1130 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1133 append_to_parent_field_class(ctx
, &fc
->base
);
1137 static inline int translate_integer_field_class(struct ctx
*ctx
)
1139 struct fs_sink_ctf_field_class_int
*fc
= fs_sink_ctf_field_class_int_create(
1140 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1143 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1147 static inline int translate_real_field_class(struct ctx
*ctx
)
1149 struct fs_sink_ctf_field_class_float
*fc
= fs_sink_ctf_field_class_float_create(
1150 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1153 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1157 static inline int translate_string_field_class(struct ctx
*ctx
)
1159 struct fs_sink_ctf_field_class_string
*fc
= fs_sink_ctf_field_class_string_create(
1160 cur_path_stack_top(ctx
)->ir_fc
, cur_path_stack_top(ctx
)->index_in_parent
);
1163 append_to_parent_field_class(ctx
, &fc
->base
);
1168 * Translates a field class, recursively.
1170 * The field class's IR field class, parent field class, and index
1171 * within its parent are in the context's current path's top element
1172 * (cur_path_stack_top()).
1174 static int translate_field_class(struct ctx
*ctx
)
1177 bt_field_class_type ir_fc_type
= bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
);
1179 if (ir_fc_type
== BT_FIELD_CLASS_TYPE_BOOL
) {
1180 ret
= translate_bool_field_class(ctx
);
1181 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_BIT_ARRAY
) {
1182 ret
= translate_bit_array_field_class(ctx
);
1183 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_INTEGER
)) {
1184 ret
= translate_integer_field_class(ctx
);
1185 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_REAL
)) {
1186 ret
= translate_real_field_class(ctx
);
1187 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STRING
) {
1188 ret
= translate_string_field_class(ctx
);
1189 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STRUCTURE
) {
1190 ret
= translate_structure_field_class(ctx
);
1191 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STATIC_ARRAY
) {
1192 ret
= translate_static_array_field_class(ctx
);
1193 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
)) {
1194 ret
= translate_dynamic_array_field_class(ctx
);
1195 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_OPTION
)) {
1196 ret
= translate_option_field_class(ctx
);
1197 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_VARIANT
)) {
1198 ret
= translate_variant_field_class(ctx
);
1206 static int set_field_ref(struct fs_sink_ctf_field_class
*fc
, const char *fc_name
,
1207 struct fs_sink_ctf_field_class
*parent_fc
)
1210 GString
*field_ref
= NULL
;
1212 const char *tgt_type
;
1213 struct fs_sink_ctf_field_class_struct
*parent_struct_fc
=
1214 fs_sink_ctf_field_class_as_struct(parent_fc
);
1216 unsigned int suffix
= 0;
1218 if (!fc_name
|| !parent_fc
|| parent_fc
->type
!= FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1225 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
1228 * CTF 1.8 does not support the option field class type.
1229 * To write something anyway, this component translates
1230 * this type to a variant field class where the options
1233 * * An empty structure field class.
1234 * * The optional field class itself.
1236 * Because the option field class becomes a CTF variant
1237 * field class, we use the term "tag" too here.
1239 * The "tag" is always generated/before in that case (an
1240 * 8-bit unsigned enumeration field class).
1242 struct fs_sink_ctf_field_class_option
*opt_fc
= fs_sink_ctf_field_class_as_option(fc
);
1244 field_ref
= opt_fc
->tag_ref
;
1249 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1251 struct fs_sink_ctf_field_class_sequence
*seq_fc
= fs_sink_ctf_field_class_as_sequence(fc
);
1253 field_ref
= seq_fc
->length_ref
;
1254 is_before
= seq_fc
->length_is_before
;
1258 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
1260 struct fs_sink_ctf_field_class_variant
*var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
1262 field_ref
= var_fc
->tag_ref
;
1263 is_before
= var_fc
->tag_is_before
;
1271 BT_ASSERT(field_ref
);
1277 /* Initial field ref */
1278 g_string_printf(field_ref
, "__%s_%s", fc_name
, tgt_type
);
1281 * Make sure field ref does not clash with an existing field
1282 * class name within the same parent structure field class.
1285 bool name_ok
= true;
1287 for (i
= 0; i
< parent_struct_fc
->members
->len
; i
++) {
1288 struct fs_sink_ctf_named_field_class
*named_fc
=
1289 fs_sink_ctf_field_class_struct_borrow_member_by_index(parent_struct_fc
, i
);
1291 if (strcmp(field_ref
->str
, named_fc
->name
->str
) == 0) {
1299 /* No clash: we're done */
1303 /* Append suffix and try again */
1304 g_string_printf(field_ref
, "__%s_%s_%u", fc_name
, tgt_type
, suffix
);
1313 * This function recursively sets field refs of sequence and variant
1314 * field classes when they are immediately before, avoiding name clashes
1315 * with existing field class names.
1317 * It can fail at this point if, for example, a sequence field class of
1318 * which to set the length's field ref has something else than a
1319 * structure field class as its parent: in this case, there's no
1320 * location to place the length field class immediately before the
1321 * sequence field class.
1323 static int set_field_refs(struct fs_sink_ctf_field_class
* const fc
, const char *fc_name
,
1324 struct fs_sink_ctf_field_class
*parent_fc
)
1327 enum fs_sink_ctf_field_class_type fc_type
;
1333 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
1335 struct fs_sink_ctf_field_class_option
*opt_fc
= fs_sink_ctf_field_class_as_option(fc
);
1337 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1342 ret
= set_field_refs(opt_fc
->content_fc
, NULL
, fc
);
1349 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
1350 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
1354 struct fs_sink_ctf_field_class_struct
*struct_fc
= NULL
;
1355 struct fs_sink_ctf_field_class_variant
*var_fc
= NULL
;
1356 struct fs_sink_ctf_named_field_class
*named_fc
;
1358 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1359 struct_fc
= fs_sink_ctf_field_class_as_struct(fc
);
1360 len
= struct_fc
->members
->len
;
1362 var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
1363 len
= var_fc
->options
->len
;
1364 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1370 for (i
= 0; i
< len
; i
++) {
1371 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1372 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
1374 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
1377 ret
= set_field_refs(named_fc
->fc
, named_fc
->name
->str
, fc
);
1385 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
1386 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1388 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
1389 fs_sink_ctf_field_class_as_array_base(fc
);
1391 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
1392 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1398 ret
= set_field_refs(array_base_fc
->elem_fc
, NULL
, fc
);
1414 * This function translates a root scope trace IR field class to
1415 * a CTF IR field class.
1417 * The resulting CTF IR field class is written to `*fc` so that it
1418 * exists as the parent object's (stream class or event class) true root
1419 * field class during the recursive translation for resolving purposes.
1420 * This is also why this function creates the empty structure field
1421 * class and then calls translate_structure_field_class_members() to
1424 static int translate_scope_field_class(struct ctx
*ctx
, bt_field_path_scope scope
,
1425 struct fs_sink_ctf_field_class
**fc
,
1426 const bt_field_class
*ir_fc
)
1434 BT_ASSERT(bt_field_class_get_type(ir_fc
) == BT_FIELD_CLASS_TYPE_STRUCTURE
);
1436 *fc
= &fs_sink_ctf_field_class_struct_create_empty(ir_fc
, UINT64_C(-1))->base
;
1438 ctx
->cur_scope
= scope
;
1439 BT_ASSERT(ctx
->cur_path
->len
== 0);
1440 ret
= cur_path_stack_push(ctx
, UINT64_C(-1), NULL
, false, ir_fc
, NULL
);
1442 BT_COMP_LOGE("Cannot translate scope structure field class: "
1449 translate_structure_field_class_members(ctx
, fs_sink_ctf_field_class_as_struct(*fc
), ir_fc
);
1451 BT_COMP_LOGE("Cannot translate scope structure field class: "
1457 cur_path_stack_pop(ctx
);
1459 /* Set field refs for preceding targets */
1460 ret
= set_field_refs(*fc
, NULL
, NULL
);
1466 static inline void ctx_init(struct ctx
*ctx
, struct fs_sink_comp
*fs_sink
)
1468 memset(ctx
, 0, sizeof(struct ctx
));
1469 ctx
->cur_path
= g_array_new(FALSE
, TRUE
, sizeof(struct field_path_elem
));
1470 BT_ASSERT(ctx
->cur_path
);
1471 ctx
->log_level
= fs_sink
->log_level
;
1472 ctx
->self_comp
= fs_sink
->self_comp
;
1475 static inline void ctx_fini(struct ctx
*ctx
)
1477 if (ctx
->cur_path
) {
1478 g_array_free(ctx
->cur_path
, TRUE
);
1479 ctx
->cur_path
= NULL
;
1483 static int translate_event_class(struct fs_sink_comp
*fs_sink
, struct fs_sink_ctf_stream_class
*sc
,
1484 const bt_event_class
*ir_ec
,
1485 struct fs_sink_ctf_event_class
**out_ec
)
1489 struct fs_sink_ctf_event_class
*ec
;
1494 ctx_init(&ctx
, fs_sink
);
1495 ec
= fs_sink_ctf_event_class_create(sc
, ir_ec
);
1499 ret
= translate_scope_field_class(
1500 &ctx
, BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
, &ec
->spec_context_fc
,
1501 bt_event_class_borrow_specific_context_field_class_const(ir_ec
));
1506 ret
= translate_scope_field_class(&ctx
, BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
, &ec
->payload_fc
,
1507 bt_event_class_borrow_payload_field_class_const(ir_ec
));
1518 int try_translate_event_class_trace_ir_to_ctf_ir(struct fs_sink_comp
*fs_sink
,
1519 struct fs_sink_ctf_stream_class
*sc
,
1520 const bt_event_class
*ir_ec
,
1521 struct fs_sink_ctf_event_class
**out_ec
)
1528 /* Check in hash table first */
1529 *out_ec
= (fs_sink_ctf_event_class
*) g_hash_table_lookup(sc
->event_classes_from_ir
, ir_ec
);
1530 if (G_LIKELY(*out_ec
)) {
1534 ret
= translate_event_class(fs_sink
, sc
, ir_ec
, out_ec
);
1540 static bool default_clock_class_name_exists(struct fs_sink_ctf_trace
*trace
, const char *name
)
1542 bool exists
= false;
1545 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1546 struct fs_sink_ctf_stream_class
*sc
=
1547 (fs_sink_ctf_stream_class
*) trace
->stream_classes
->pdata
[i
];
1549 if (sc
->default_clock_class_name
->len
== 0) {
1550 /* No default clock class */
1554 if (strcmp(sc
->default_clock_class_name
->str
, name
) == 0) {
1564 static void make_unique_default_clock_class_name(struct fs_sink_ctf_stream_class
*sc
)
1566 unsigned int suffix
= 0;
1568 std::string name
= "default";
1570 while (default_clock_class_name_exists(sc
->trace
, name
.c_str())) {
1571 name
= "default" + std::to_string(suffix
);
1575 g_string_assign(sc
->default_clock_class_name
, name
.c_str());
1578 static int translate_stream_class(struct fs_sink_comp
*fs_sink
, struct fs_sink_ctf_trace
*trace
,
1579 const bt_stream_class
*ir_sc
,
1580 struct fs_sink_ctf_stream_class
**out_sc
)
1587 ctx_init(&ctx
, fs_sink
);
1588 *out_sc
= fs_sink_ctf_stream_class_create(trace
, ir_sc
);
1591 /* Set default clock class's protected name, if any */
1592 if ((*out_sc
)->default_clock_class
) {
1593 const char *name
= bt_clock_class_get_name((*out_sc
)->default_clock_class
);
1596 /* Try original name, protected */
1597 g_string_assign((*out_sc
)->default_clock_class_name
, "");
1599 if (must_protect_identifier(name
)) {
1600 g_string_assign((*out_sc
)->default_clock_class_name
, "_");
1603 g_string_assign((*out_sc
)->default_clock_class_name
, name
);
1604 if (!ist_valid_identifier((*out_sc
)->default_clock_class_name
->str
)) {
1605 /* Invalid: create a new name */
1606 make_unique_default_clock_class_name(*out_sc
);
1609 /* No name: create a name */
1610 make_unique_default_clock_class_name(*out_sc
);
1614 ctx
.cur_sc
= *out_sc
;
1615 ret
= translate_scope_field_class(
1616 &ctx
, BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
, &(*out_sc
)->packet_context_fc
,
1617 bt_stream_class_borrow_packet_context_field_class_const(ir_sc
));
1622 if ((*out_sc
)->packet_context_fc
) {
1624 * Make sure the structure field class's alignment is
1625 * enough: 8 is what we use for our own special members
1626 * in the packet context.
1628 fs_sink_ctf_field_class_struct_align_at_least(
1629 fs_sink_ctf_field_class_as_struct((*out_sc
)->packet_context_fc
), 8);
1632 ret
= translate_scope_field_class(
1633 &ctx
, BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
, &(*out_sc
)->event_common_context_fc
,
1634 bt_stream_class_borrow_event_common_context_field_class_const(ir_sc
));
1642 fs_sink_ctf_stream_class_destroy(*out_sc
);
1650 int try_translate_stream_class_trace_ir_to_ctf_ir(struct fs_sink_comp
*fs_sink
,
1651 struct fs_sink_ctf_trace
*trace
,
1652 const bt_stream_class
*ir_sc
,
1653 struct fs_sink_ctf_stream_class
**out_sc
)
1661 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1662 *out_sc
= (fs_sink_ctf_stream_class
*) trace
->stream_classes
->pdata
[i
];
1664 if ((*out_sc
)->ir_sc
== ir_sc
) {
1669 ret
= translate_stream_class(fs_sink
, trace
, ir_sc
, out_sc
);
1675 struct fs_sink_ctf_trace
*translate_trace_trace_ir_to_ctf_ir(struct fs_sink_comp
*fs_sink
,
1676 const bt_trace
*ir_trace
)
1680 struct fs_sink_ctf_trace
*trace
= NULL
;
1682 /* Check that trace's environment is TSDL-compatible */
1683 count
= bt_trace_get_environment_entry_count(ir_trace
);
1684 for (i
= 0; i
< count
; i
++) {
1686 const bt_value
*val
;
1688 bt_trace_borrow_environment_entry_by_index_const(ir_trace
, i
, &name
, &val
);
1690 if (!ist_valid_identifier(name
)) {
1691 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
, fs_sink
->self_comp
,
1692 "Unsupported trace class's environment entry name: "
1698 switch (bt_value_get_type(val
)) {
1699 case BT_VALUE_TYPE_SIGNED_INTEGER
:
1700 case BT_VALUE_TYPE_STRING
:
1703 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
, fs_sink
->self_comp
,
1704 "Unsupported trace class's environment entry value type: "
1706 bt_common_value_type_string(bt_value_get_type(val
)));
1711 trace
= fs_sink_ctf_trace_create(ir_trace
);