2 * SPDX-License-Identifier: MIT
4 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
13 #include <babeltrace2/babeltrace.h>
15 #define BT_COMP_LOG_SELF_COMP (ctx->self_comp)
16 #define BT_LOG_OUTPUT_LEVEL (ctx->log_level)
17 #define BT_LOG_TAG "PLUGIN/SINK.CTF.FS/TRANSLATE-TRACE-IR-TO-CTF-IR"
18 #include "logging/comp-logging.h"
20 #include "common/assert.h"
21 #include "common/common.h"
23 #include "fs-sink-ctf-meta.hpp"
24 #include "fs-sink.hpp"
25 #include "translate-trace-ir-to-ctf-ir.hpp"
27 struct field_path_elem
32 const bt_field_class
*ir_fc
;
35 struct fs_sink_ctf_field_class
*parent_fc
;
41 struct TraceIrToCtfIrCtx
43 bt_logging_level log_level
= BT_LOGGING_LEVEL_NONE
;
44 bt_self_component
*self_comp
= nullptr;
47 struct fs_sink_ctf_stream_class
*cur_sc
= nullptr;
50 struct fs_sink_ctf_event_class
*cur_ec
= nullptr;
52 bt_field_path_scope cur_scope
= BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
;
55 * Array of `struct field_path_elem` */
56 GArray
*cur_path
= nullptr;
59 } /* namespace sink */
62 static inline struct field_path_elem
*cur_path_stack_at(ctf::sink::TraceIrToCtfIrCtx
*ctx
,
65 BT_ASSERT(i
< ctx
->cur_path
->len
);
66 return &bt_g_array_index(ctx
->cur_path
, struct field_path_elem
, i
);
69 static inline struct field_path_elem
*cur_path_stack_top(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
71 BT_ASSERT(ctx
->cur_path
->len
> 0);
72 return cur_path_stack_at(ctx
, ctx
->cur_path
->len
- 1);
75 static inline bool is_reserved_member_name(const char *name
, const char *reserved_name
)
77 bool is_reserved
= false;
79 if (strcmp(name
, reserved_name
) == 0) {
84 if (name
[0] == '_' && strcmp(&name
[1], reserved_name
) == 0) {
93 static const char *reserved_tsdl_keywords
[] = {
94 "align", "callsite", "const", "char", "clock", "double", "enum",
95 "env", "event", "floating_point", "float", "integer", "int", "long",
96 "short", "signed", "stream", "string", "struct", "trace", "typealias",
97 "typedef", "unsigned", "variant", "void", "_Bool", "_Complex", "_Imaginary",
100 static inline bool ist_valid_identifier(const char *name
)
104 bool ist_valid
= true;
106 /* Make sure the name is not a reserved keyword */
107 for (i
= 0; i
< sizeof(reserved_tsdl_keywords
) / sizeof(*reserved_tsdl_keywords
); i
++) {
108 if (strcmp(name
, reserved_tsdl_keywords
[i
]) == 0) {
114 /* Make sure the name is not an empty string */
115 if (strlen(name
) == 0) {
120 /* Make sure the name starts with a letter or `_` */
121 if (!isalpha((unsigned char) name
[0]) && name
[0] != '_') {
126 /* Make sure the name only contains letters, digits, and `_` */
127 for (at
= name
; *at
!= '\0'; at
++) {
128 if (!isalnum((unsigned char) *at
) && *at
!= '_') {
138 static inline bool must_protect_identifier(const char *name
)
141 bool must_protect
= false;
143 /* Protect a reserved keyword */
144 for (i
= 0; i
< sizeof(reserved_tsdl_keywords
) / sizeof(*reserved_tsdl_keywords
); i
++) {
145 if (strcmp(name
, reserved_tsdl_keywords
[i
]) == 0) {
151 /* Protect an identifier which already starts with `_` */
152 if (name
[0] == '_') {
161 static inline int cur_path_stack_push(ctf::sink::TraceIrToCtfIrCtx
*ctx
, const char *name
,
162 bool force_protect_name
, const bt_field_class
*ir_fc
,
163 struct fs_sink_ctf_field_class
*parent_fc
)
166 struct field_path_elem
*field_path_elem
;
168 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
+ 1);
169 field_path_elem
= cur_path_stack_top(ctx
);
170 field_path_elem
->name
= g_string_new(NULL
);
173 if (force_protect_name
) {
174 g_string_assign(field_path_elem
->name
, "_");
177 g_string_append(field_path_elem
->name
, name
);
179 if (ctx
->cur_scope
== BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
) {
180 if (is_reserved_member_name(name
, "packet_size") ||
181 is_reserved_member_name(name
, "content_size") ||
182 is_reserved_member_name(name
, "timestamp_begin") ||
183 is_reserved_member_name(name
, "timestamp_end") ||
184 is_reserved_member_name(name
, "events_discarded") ||
185 is_reserved_member_name(name
, "packet_seq_num")) {
186 BT_COMP_LOGE("Unsupported reserved TSDL structure field class member "
187 "or variant field class option name: name=\"%s\"",
194 if (!ist_valid_identifier(field_path_elem
->name
->str
)) {
196 BT_COMP_LOGE("Unsupported non-TSDL structure field class member "
197 "or variant field class option name: name=\"%s\"",
198 field_path_elem
->name
->str
);
203 field_path_elem
->ir_fc
= ir_fc
;
204 field_path_elem
->parent_fc
= parent_fc
;
210 static inline void cur_path_stack_pop(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
212 struct field_path_elem
*field_path_elem
;
214 BT_ASSERT(ctx
->cur_path
->len
> 0);
215 field_path_elem
= cur_path_stack_top(ctx
);
217 if (field_path_elem
->name
) {
218 g_string_free(field_path_elem
->name
, TRUE
);
219 field_path_elem
->name
= NULL
;
222 g_array_set_size(ctx
->cur_path
, ctx
->cur_path
->len
- 1);
226 * Creates a relative field ref (a single name) from IR field path
227 * `tgt_ir_field_path`.
229 * This function tries to locate the target field class recursively from
230 * the top to the bottom of the context's current path using only the
231 * target field class's own name. This is because many CTF reading tools
232 * do not support a relative field ref with more than one element, for
233 * example `prev_struct.len`.
235 * Returns a negative value if this resolving operation failed.
237 static int create_relative_field_ref(ctf::sink::TraceIrToCtfIrCtx
*ctx
,
238 const bt_field_path
*tgt_ir_field_path
, GString
*tgt_field_ref
,
239 struct fs_sink_ctf_field_class
**user_tgt_fc
)
242 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
245 const char *tgt_fc_name
= NULL
;
246 struct field_path_elem
*field_path_elem
;
248 /* Get target field class's name */
249 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
250 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
251 BT_ASSERT(ctx
->cur_sc
);
252 tgt_fc
= ctx
->cur_sc
->packet_context_fc
;
254 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
255 BT_ASSERT(ctx
->cur_sc
);
256 tgt_fc
= ctx
->cur_sc
->event_common_context_fc
;
258 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
259 BT_ASSERT(ctx
->cur_ec
);
260 tgt_fc
= ctx
->cur_ec
->spec_context_fc
;
262 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
263 BT_ASSERT(ctx
->cur_ec
);
264 tgt_fc
= ctx
->cur_ec
->payload_fc
;
272 while (i
< bt_field_path_get_item_count(tgt_ir_field_path
)) {
273 const bt_field_path_item
*fp_item
=
274 bt_field_path_borrow_item_by_index_const(tgt_ir_field_path
, i
);
275 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
280 if (bt_field_path_item_get_type(fp_item
) ==
281 BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT
) {
282 /* Not supported by CTF 1.8 */
287 switch (tgt_fc
->type
) {
288 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
289 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
290 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
291 fs_sink_ctf_field_class_as_struct(tgt_fc
),
292 bt_field_path_item_index_get_index(fp_item
));
294 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
295 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
296 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
297 fs_sink_ctf_field_class_as_variant(tgt_fc
),
298 bt_field_path_item_index_get_index(fp_item
));
300 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
301 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
303 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
304 fs_sink_ctf_field_class_as_array_base(tgt_fc
);
306 BT_ASSERT(bt_field_path_item_get_type(fp_item
) ==
307 BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT
);
308 tgt_fc
= array_base_fc
->elem_fc
;
316 tgt_fc
= named_fc
->fc
;
317 tgt_fc_name
= named_fc
->name
->str
;
323 BT_ASSERT(tgt_fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_INT
);
324 BT_ASSERT(tgt_fc_name
);
326 /* Find target field class having this name in current context */
327 for (si
= ctx
->cur_path
->len
- 1; si
>= 0; si
--) {
328 struct fs_sink_ctf_field_class
*fc
;
329 struct fs_sink_ctf_field_class_struct
*struct_fc
= NULL
;
330 struct fs_sink_ctf_field_class_variant
*var_fc
= NULL
;
331 struct fs_sink_ctf_named_field_class
*named_fc
;
334 field_path_elem
= cur_path_stack_at(ctx
, (uint64_t) si
);
335 fc
= field_path_elem
->parent_fc
;
337 /* Reached stack's bottom */
343 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
344 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
346 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
347 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
350 /* Not supported by TSDL 1.8 */
355 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
356 struct_fc
= fs_sink_ctf_field_class_as_struct(fc
);
357 len
= struct_fc
->members
->len
;
359 var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
360 len
= var_fc
->options
->len
;
363 for (i
= 0; i
< len
; i
++) {
364 if (fc
->type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
365 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
367 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
370 if (strcmp(named_fc
->name
->str
, tgt_fc_name
) == 0) {
371 if (named_fc
->fc
== tgt_fc
) {
372 g_string_assign(tgt_field_ref
, tgt_fc_name
);
375 *user_tgt_fc
= tgt_fc
;
379 * Using only the target field
380 * class's name, we're not
381 * reaching the target field
382 * class. This is not supported
398 * Creates an absolute field ref from IR field path `tgt_ir_field_path`.
400 * Returns a negative value if this resolving operation failed.
402 static int create_absolute_field_ref(ctf::sink::TraceIrToCtfIrCtx
*ctx
,
403 const bt_field_path
*tgt_ir_field_path
, GString
*tgt_field_ref
,
404 struct fs_sink_ctf_field_class
**user_tgt_fc
)
407 struct fs_sink_ctf_field_class
*fc
= NULL
;
410 switch (bt_field_path_get_root_scope(tgt_ir_field_path
)) {
411 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
:
412 BT_ASSERT(ctx
->cur_sc
);
413 fc
= ctx
->cur_sc
->packet_context_fc
;
414 g_string_assign(tgt_field_ref
, "stream.packet.context");
416 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
:
417 BT_ASSERT(ctx
->cur_sc
);
418 fc
= ctx
->cur_sc
->event_common_context_fc
;
419 g_string_assign(tgt_field_ref
, "stream.event.context");
421 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
:
422 BT_ASSERT(ctx
->cur_ec
);
423 fc
= ctx
->cur_ec
->spec_context_fc
;
424 g_string_assign(tgt_field_ref
, "event.context");
426 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
:
427 BT_ASSERT(ctx
->cur_ec
);
428 fc
= ctx
->cur_ec
->payload_fc
;
429 g_string_assign(tgt_field_ref
, "event.fields");
437 for (i
= 0; i
< bt_field_path_get_item_count(tgt_ir_field_path
); i
++) {
438 const bt_field_path_item
*fp_item
=
439 bt_field_path_borrow_item_by_index_const(tgt_ir_field_path
, i
);
440 struct fs_sink_ctf_named_field_class
*named_fc
= NULL
;
442 if (bt_field_path_item_get_type(fp_item
) != BT_FIELD_PATH_ITEM_TYPE_INDEX
) {
443 /* Not supported by TSDL 1.8 */
449 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
450 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
451 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(
452 fs_sink_ctf_field_class_as_struct(fc
), bt_field_path_item_index_get_index(fp_item
));
454 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
455 BT_ASSERT(bt_field_path_item_get_type(fp_item
) == BT_FIELD_PATH_ITEM_TYPE_INDEX
);
456 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(
457 fs_sink_ctf_field_class_as_variant(fc
),
458 bt_field_path_item_index_get_index(fp_item
));
465 g_string_append_c(tgt_field_ref
, '.');
466 g_string_append(tgt_field_ref
, named_fc
->name
->str
);
479 * Resolves a target field class located at `tgt_ir_field_path`, writing
480 * the resolved field ref to `tgt_field_ref` and setting
481 * `*create_before` according to whether or not the target field must be
482 * created immediately before (in which case `tgt_field_ref` is
485 static void resolve_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
,
486 const bt_field_path
*tgt_ir_field_path
, GString
*tgt_field_ref
,
487 bool *create_before
, struct fs_sink_ctf_field_class
**user_tgt_fc
)
490 bt_field_path_scope tgt_scope
;
492 *create_before
= false;
494 if (!tgt_ir_field_path
) {
495 *create_before
= true;
499 tgt_scope
= bt_field_path_get_root_scope(tgt_ir_field_path
);
501 if (tgt_scope
== ctx
->cur_scope
) {
503 * Try, in this order:
505 * 1. Use a relative path, using only the target field
506 * class's name. This is what is the most commonly
507 * supported by popular CTF reading tools.
509 * 2. Use an absolute path. This could fail if there's
510 * an array field class from the current root's field
511 * class to the target field class.
513 * 3. Create the target field class before the
514 * requesting field class (fallback).
516 ret
= create_relative_field_ref(ctx
, tgt_ir_field_path
, tgt_field_ref
, user_tgt_fc
);
518 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
, tgt_field_ref
, user_tgt_fc
);
520 *create_before
= true;
525 ret
= create_absolute_field_ref(ctx
, tgt_ir_field_path
, tgt_field_ref
, user_tgt_fc
);
527 /* It must always work in previous scopes */
535 static int translate_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
);
537 static inline void append_to_parent_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
,
538 struct fs_sink_ctf_field_class
*fc
)
540 struct fs_sink_ctf_field_class
*parent_fc
= cur_path_stack_top(ctx
)->parent_fc
;
542 switch (parent_fc
->type
) {
543 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
544 fs_sink_ctf_field_class_struct_append_member(fs_sink_ctf_field_class_as_struct(parent_fc
),
545 cur_path_stack_top(ctx
)->name
->str
, fc
);
547 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
549 struct fs_sink_ctf_field_class_option
*opt_fc
=
550 fs_sink_ctf_field_class_as_option(parent_fc
);
552 BT_ASSERT(!opt_fc
->content_fc
);
553 opt_fc
->content_fc
= fc
;
554 opt_fc
->base
.alignment
= fc
->alignment
;
557 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
558 fs_sink_ctf_field_class_variant_append_option(fs_sink_ctf_field_class_as_variant(parent_fc
),
559 cur_path_stack_top(ctx
)->name
->str
, fc
);
561 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
562 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
564 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
565 fs_sink_ctf_field_class_as_array_base(parent_fc
);
567 BT_ASSERT(!array_base_fc
->elem_fc
);
568 array_base_fc
->elem_fc
= fc
;
569 array_base_fc
->base
.alignment
= fc
->alignment
;
577 static inline void update_parent_field_class_alignment(ctf::sink::TraceIrToCtfIrCtx
*ctx
,
578 unsigned int alignment
)
580 struct fs_sink_ctf_field_class
*parent_fc
= cur_path_stack_top(ctx
)->parent_fc
;
582 switch (parent_fc
->type
) {
583 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
584 fs_sink_ctf_field_class_struct_align_at_least(fs_sink_ctf_field_class_as_struct(parent_fc
),
587 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
588 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
590 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
591 fs_sink_ctf_field_class_as_array_base(parent_fc
);
593 array_base_fc
->base
.alignment
= alignment
;
602 translate_structure_field_class_members(ctf::sink::TraceIrToCtfIrCtx
*ctx
,
603 struct fs_sink_ctf_field_class_struct
*struct_fc
,
604 const bt_field_class
*ir_fc
)
609 for (i
= 0; i
< bt_field_class_structure_get_member_count(ir_fc
); i
++) {
610 const bt_field_class_structure_member
*member
;
612 const bt_field_class
*memb_ir_fc
;
614 member
= bt_field_class_structure_borrow_member_by_index_const(ir_fc
, i
);
615 name
= bt_field_class_structure_member_get_name(member
);
616 memb_ir_fc
= bt_field_class_structure_member_borrow_field_class_const(member
);
617 ret
= cur_path_stack_push(ctx
, name
, true, memb_ir_fc
, &struct_fc
->base
);
619 BT_COMP_LOGE("Cannot translate structure field class member: "
625 ret
= translate_field_class(ctx
);
627 BT_COMP_LOGE("Cannot translate structure field class member: "
633 cur_path_stack_pop(ctx
);
640 static inline int translate_structure_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
643 struct fs_sink_ctf_field_class_struct
*fc
=
644 fs_sink_ctf_field_class_struct_create_empty(cur_path_stack_top(ctx
)->ir_fc
);
647 append_to_parent_field_class(ctx
, &fc
->base
);
648 ret
= translate_structure_field_class_members(ctx
, fc
, fc
->base
.ir_fc
);
653 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
660 * This function protects a given variant FC option name (with the `_`
661 * prefix) if required. On success, `name_buf->str` contains the variant
662 * FC option name to use (original option name or protected if
665 * One of the goals of `sink.ctf.fs` is to write a CTF trace which is as
666 * close as possible to an original CTF trace as decoded by
669 * This scenario is valid in CTF 1.8:
681 * Once in trace IR, the enumeration FC mapping names and variant FC
682 * option names are kept as is. For this reason, we don't want to
683 * protect the variant FC option names here (by prepending `_`): this
684 * would make the variant FC option name and the enumeration FC mapping
687 * This scenario is also valid in CTF 1.8:
699 * Once in trace IR, the enumeration FC mapping names are kept as is,
700 * but the `_HELLO` variant FC option name becomes `HELLO` (unprotected
701 * for presentation, as recommended by CTF 1.8). When going back to
702 * TSDL, we need to protect `HELLO` so that it becomes `_HELLO` to match
703 * the corresponding enumeration FC mapping name.
705 * This scenario is also valid in CTF 1.8:
717 * Once in trace IR, the enumeration FC mapping names are kept as is,
718 * but the `__HELLO` variant FC option name becomes `_HELLO`
719 * (unprotected). When going back to TSDL, we need to protect `_HELLO`
720 * so that it becomes `__HELLO` to match the corresponding enumeration
723 * `src.ctf.fs` always uses the _same_ integer range sets for a selector
724 * FC mapping and a corresponding variant FC option. We can use that
725 * fact to find the original variant FC option names by matching variant
726 * FC options and enumeration FC mappings by range set.
728 static int maybe_protect_variant_option_name(const bt_field_class
*ir_var_fc
,
729 const bt_field_class
*ir_tag_fc
, uint64_t opt_i
,
734 bt_field_class_type ir_var_fc_type
;
735 const bt_integer_range_set_unsigned
*opt_ranges_unsigned
= NULL
;
736 const bt_integer_range_set_signed
*opt_ranges_signed
= NULL
;
737 const char *mapping_label
= NULL
;
738 const char *ir_opt_name
;
739 const bt_field_class_variant_option
*base_var_opt
;
740 bool force_protect
= false;
742 ir_var_fc_type
= bt_field_class_get_type(ir_var_fc
);
743 base_var_opt
= bt_field_class_variant_borrow_option_by_index_const(ir_var_fc
, opt_i
);
744 BT_ASSERT(base_var_opt
);
745 ir_opt_name
= bt_field_class_variant_option_get_name(base_var_opt
);
746 BT_ASSERT(ir_opt_name
);
749 * Check if the variant FC option name is required to be
750 * protected (reserved TSDL keyword or starts with `_`). In that
751 * case, the name of the selector FC mapping we find must match
752 * exactly the protected name.
754 force_protect
= must_protect_identifier(ir_opt_name
);
756 g_string_assign(name_buf
, "_");
757 g_string_append(name_buf
, ir_opt_name
);
759 g_string_assign(name_buf
, ir_opt_name
);
762 /* Borrow option's ranges */
763 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD
) {
764 /* No ranges: we're done */
767 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
) {
768 const bt_field_class_variant_with_selector_field_integer_unsigned_option
*var_opt
=
769 bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_index_const(
771 opt_ranges_unsigned
=
772 bt_field_class_variant_with_selector_field_integer_unsigned_option_borrow_ranges_const(
775 const bt_field_class_variant_with_selector_field_integer_signed_option
*var_opt
=
776 bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_index_const(
779 bt_field_class_variant_with_selector_field_integer_signed_option_borrow_ranges_const(
783 /* Find corresponding mapping by range set in selector FC */
784 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(ir_tag_fc
); i
++) {
785 if (ir_var_fc_type
== BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
) {
786 const bt_field_class_enumeration_mapping
*mapping_base
;
787 const bt_field_class_enumeration_unsigned_mapping
*mapping
;
788 const bt_integer_range_set_unsigned
*mapping_ranges
;
791 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(ir_tag_fc
, i
);
793 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(mapping
);
795 if (bt_integer_range_set_unsigned_is_equal(opt_ranges_unsigned
, mapping_ranges
)) {
796 /* We have a winner */
798 bt_field_class_enumeration_unsigned_mapping_as_mapping_const(mapping
);
799 mapping_label
= bt_field_class_enumeration_mapping_get_label(mapping_base
);
803 const bt_field_class_enumeration_mapping
*mapping_base
;
804 const bt_field_class_enumeration_signed_mapping
*mapping
;
805 const bt_integer_range_set_signed
*mapping_ranges
;
807 mapping
= bt_field_class_enumeration_signed_borrow_mapping_by_index_const(ir_tag_fc
, i
);
808 mapping_ranges
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(mapping
);
810 if (bt_integer_range_set_signed_is_equal(opt_ranges_signed
, mapping_ranges
)) {
811 /* We have a winner */
812 mapping_base
= bt_field_class_enumeration_signed_mapping_as_mapping_const(mapping
);
813 mapping_label
= bt_field_class_enumeration_mapping_get_label(mapping_base
);
819 if (!mapping_label
) {
820 /* Range set not found: invalid selector for CTF 1.8 */
826 * If the enumeration FC mapping name is not the same as the
827 * variant FC option name and we didn't protect already, try
828 * protecting the option name and check again.
830 if (strcmp(mapping_label
, name_buf
->str
) != 0) {
836 if (mapping_label
[0] == '\0') {
841 g_string_assign(name_buf
, "_");
842 g_string_append(name_buf
, ir_opt_name
);
844 if (strcmp(mapping_label
, name_buf
->str
) != 0) {
854 static inline int translate_option_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
856 struct fs_sink_ctf_field_class_option
*fc
=
857 fs_sink_ctf_field_class_option_create_empty(cur_path_stack_top(ctx
)->ir_fc
);
858 const bt_field_class
*content_ir_fc
=
859 bt_field_class_option_borrow_field_class_const(fc
->base
.ir_fc
);
865 * CTF 1.8 does not support the option field class type. To
866 * write something anyway, this component translates this type
867 * to a variant field class where the options are:
869 * * An empty structure field class.
870 * * The optional field class itself.
872 * The "tag" is always generated/before in that case (an 8-bit
873 * unsigned enumeration field class).
875 append_to_parent_field_class(ctx
, &fc
->base
);
876 ret
= cur_path_stack_push(ctx
, NULL
, false, content_ir_fc
, &fc
->base
);
878 BT_COMP_LOGE_STR("Cannot translate option field class content.");
882 ret
= translate_field_class(ctx
);
884 BT_COMP_LOGE_STR("Cannot translate option field class content.");
888 cur_path_stack_pop(ctx
);
889 update_parent_field_class_alignment(ctx
, fc
->base
.alignment
);
895 static inline int translate_variant_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
899 struct fs_sink_ctf_field_class_variant
*fc
=
900 fs_sink_ctf_field_class_variant_create_empty(cur_path_stack_top(ctx
)->ir_fc
);
901 bt_field_class_type ir_fc_type
;
902 const bt_field_path
*ir_selector_field_path
= NULL
;
903 struct fs_sink_ctf_field_class
*tgt_fc
= NULL
;
904 GString
*name_buf
= g_string_new(NULL
);
905 bt_value
*prot_opt_names
= bt_value_array_create();
910 BT_ASSERT(prot_opt_names
);
911 ir_fc_type
= bt_field_class_get_type(fc
->base
.ir_fc
);
912 opt_count
= bt_field_class_variant_get_option_count(fc
->base
.ir_fc
);
914 if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_VARIANT_WITH_SELECTOR_FIELD
)) {
915 ir_selector_field_path
=
916 bt_field_class_variant_with_selector_field_borrow_selector_field_path_const(
918 BT_ASSERT(ir_selector_field_path
);
921 /* Resolve tag field class before appending to parent */
922 resolve_field_class(ctx
, ir_selector_field_path
, fc
->tag_ref
, &fc
->tag_is_before
, &tgt_fc
);
924 if (ir_selector_field_path
&& tgt_fc
) {
925 uint64_t mapping_count
;
926 uint64_t option_count
;
928 /* CTF 1.8: selector FC must be an enumeration FC */
929 bt_field_class_type type
= bt_field_class_get_type(tgt_fc
->ir_fc
);
931 if (!bt_field_class_type_is(type
, BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
932 fc
->tag_is_before
= true;
937 * Call maybe_protect_variant_option_name() for each
938 * option below. In that case we also want selector FC
939 * to contain as many mappings as the variant FC has
942 mapping_count
= bt_field_class_enumeration_get_mapping_count(tgt_fc
->ir_fc
);
943 option_count
= bt_field_class_variant_get_option_count(fc
->base
.ir_fc
);
945 if (mapping_count
!= option_count
) {
946 fc
->tag_is_before
= true;
951 * No compatible selector field class for CTF 1.8:
952 * create the appropriate selector field class.
954 fc
->tag_is_before
= true;
960 * First pass: detect any option name clash with option name
961 * protection. In that case, we don't fail: just create the
962 * selector field class before the variant field class.
964 * After this, `prot_opt_names` contains the final option names,
965 * potentially protected if needed. They can still be invalid
966 * TSDL identifiers however; this will be checked by
967 * cur_path_stack_push().
969 for (i
= 0; i
< opt_count
; i
++) {
970 if (!fc
->tag_is_before
) {
971 BT_ASSERT(tgt_fc
->ir_fc
);
972 ret
= maybe_protect_variant_option_name(fc
->base
.ir_fc
, tgt_fc
->ir_fc
, i
, name_buf
);
974 fc
->tag_is_before
= true;
978 ret
= bt_value_array_append_string_element(prot_opt_names
, name_buf
->str
);
984 for (i
= 0; i
< opt_count
; i
++) {
986 const bt_value
*opt_name_a
=
987 bt_value_array_borrow_element_by_index_const(prot_opt_names
, i
);
989 for (j
= 0; j
< opt_count
; j
++) {
990 const bt_value
*opt_name_b
;
996 opt_name_b
= bt_value_array_borrow_element_by_index_const(prot_opt_names
, j
);
997 if (bt_value_is_equal(opt_name_a
, opt_name_b
)) {
999 * Variant FC option names are not
1000 * unique when protected.
1002 fc
->tag_is_before
= true;
1003 goto append_to_parent
;
1009 append_to_parent_field_class(ctx
, &fc
->base
);
1011 for (i
= 0; i
< opt_count
; i
++) {
1012 const bt_field_class_variant_option
*opt
;
1013 const bt_field_class
*opt_ir_fc
;
1014 const bt_value
*prot_opt_name_val
=
1015 bt_value_array_borrow_element_by_index_const(prot_opt_names
, i
);
1016 const char *prot_opt_name
= bt_value_string_get(prot_opt_name_val
);
1018 BT_ASSERT(prot_opt_name
);
1019 opt
= bt_field_class_variant_borrow_option_by_index_const(fc
->base
.ir_fc
, i
);
1020 opt_ir_fc
= bt_field_class_variant_option_borrow_field_class_const(opt
);
1023 * We don't ask cur_path_stack_push() to protect the
1024 * option name because it's already protected at this
1027 ret
= cur_path_stack_push(ctx
, prot_opt_name
, false, opt_ir_fc
, &fc
->base
);
1029 BT_COMP_LOGE("Cannot translate variant field class option: "
1035 ret
= translate_field_class(ctx
);
1037 BT_COMP_LOGE("Cannot translate variant field class option: "
1043 cur_path_stack_pop(ctx
);
1048 g_string_free(name_buf
, TRUE
);
1051 bt_value_put_ref(prot_opt_names
);
1055 static inline int translate_static_array_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
1057 struct fs_sink_ctf_field_class_array
*fc
=
1058 fs_sink_ctf_field_class_array_create_empty(cur_path_stack_top(ctx
)->ir_fc
);
1059 const bt_field_class
*elem_ir_fc
=
1060 bt_field_class_array_borrow_element_field_class_const(fc
->base
.base
.ir_fc
);
1064 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1065 ret
= cur_path_stack_push(ctx
, NULL
, false, elem_ir_fc
, &fc
->base
.base
);
1067 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1071 ret
= translate_field_class(ctx
);
1073 BT_COMP_LOGE_STR("Cannot translate static array field class element.");
1077 cur_path_stack_pop(ctx
);
1078 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
1084 static inline int translate_dynamic_array_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
1086 struct fs_sink_ctf_field_class_sequence
*fc
=
1087 fs_sink_ctf_field_class_sequence_create_empty(cur_path_stack_top(ctx
)->ir_fc
);
1088 const bt_field_class
*elem_ir_fc
=
1089 bt_field_class_array_borrow_element_field_class_const(fc
->base
.base
.ir_fc
);
1094 /* Resolve length field class before appending to parent */
1095 if (bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
) ==
1096 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
) {
1097 resolve_field_class(
1099 bt_field_class_array_dynamic_with_length_field_borrow_length_field_path_const(
1100 fc
->base
.base
.ir_fc
),
1101 fc
->length_ref
, &fc
->length_is_before
, NULL
);
1104 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1105 ret
= cur_path_stack_push(ctx
, NULL
, false, elem_ir_fc
, &fc
->base
.base
);
1107 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1111 ret
= translate_field_class(ctx
);
1113 BT_COMP_LOGE_STR("Cannot translate dynamic array field class element.");
1117 cur_path_stack_pop(ctx
);
1118 update_parent_field_class_alignment(ctx
, fc
->base
.base
.alignment
);
1124 static inline int translate_bool_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
1126 struct fs_sink_ctf_field_class_bool
*fc
=
1127 fs_sink_ctf_field_class_bool_create(cur_path_stack_top(ctx
)->ir_fc
);
1130 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1134 static inline int translate_bit_array_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
1136 struct fs_sink_ctf_field_class_bit_array
*fc
=
1137 fs_sink_ctf_field_class_bit_array_create(cur_path_stack_top(ctx
)->ir_fc
);
1140 append_to_parent_field_class(ctx
, &fc
->base
);
1144 static inline int translate_integer_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
1146 struct fs_sink_ctf_field_class_int
*fc
=
1147 fs_sink_ctf_field_class_int_create(cur_path_stack_top(ctx
)->ir_fc
);
1150 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1154 static inline int translate_real_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
1156 struct fs_sink_ctf_field_class_float
*fc
=
1157 fs_sink_ctf_field_class_float_create(cur_path_stack_top(ctx
)->ir_fc
);
1160 append_to_parent_field_class(ctx
, &fc
->base
.base
);
1164 static inline int translate_string_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
1166 struct fs_sink_ctf_field_class_string
*fc
=
1167 fs_sink_ctf_field_class_string_create(cur_path_stack_top(ctx
)->ir_fc
);
1170 append_to_parent_field_class(ctx
, &fc
->base
);
1175 * Translates a field class, recursively.
1177 * The field class's IR field class, parent field class, and index
1178 * within its parent are in the context's current path's top element
1179 * (cur_path_stack_top()).
1181 static int translate_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
1184 bt_field_class_type ir_fc_type
= bt_field_class_get_type(cur_path_stack_top(ctx
)->ir_fc
);
1186 if (ir_fc_type
== BT_FIELD_CLASS_TYPE_BOOL
) {
1187 ret
= translate_bool_field_class(ctx
);
1188 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_BIT_ARRAY
) {
1189 ret
= translate_bit_array_field_class(ctx
);
1190 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_INTEGER
)) {
1191 ret
= translate_integer_field_class(ctx
);
1192 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_REAL
)) {
1193 ret
= translate_real_field_class(ctx
);
1194 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STRING
) {
1195 ret
= translate_string_field_class(ctx
);
1196 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STRUCTURE
) {
1197 ret
= translate_structure_field_class(ctx
);
1198 } else if (ir_fc_type
== BT_FIELD_CLASS_TYPE_STATIC_ARRAY
) {
1199 ret
= translate_static_array_field_class(ctx
);
1200 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
)) {
1201 ret
= translate_dynamic_array_field_class(ctx
);
1202 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_OPTION
)) {
1203 ret
= translate_option_field_class(ctx
);
1204 } else if (bt_field_class_type_is(ir_fc_type
, BT_FIELD_CLASS_TYPE_VARIANT
)) {
1205 ret
= translate_variant_field_class(ctx
);
1213 static int set_field_ref(struct fs_sink_ctf_field_class
*fc
, const char *fc_name
,
1214 struct fs_sink_ctf_field_class
*parent_fc
)
1217 GString
*field_ref
= NULL
;
1219 const char *tgt_type
;
1220 struct fs_sink_ctf_field_class_struct
*parent_struct_fc
=
1221 fs_sink_ctf_field_class_as_struct(parent_fc
);
1223 unsigned int suffix
= 0;
1225 if (!fc_name
|| !parent_fc
|| parent_fc
->type
!= FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1232 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
1235 * CTF 1.8 does not support the option field class type.
1236 * To write something anyway, this component translates
1237 * this type to a variant field class where the options
1240 * * An empty structure field class.
1241 * * The optional field class itself.
1243 * Because the option field class becomes a CTF variant
1244 * field class, we use the term "tag" too here.
1246 * The "tag" is always generated/before in that case (an
1247 * 8-bit unsigned enumeration field class).
1249 struct fs_sink_ctf_field_class_option
*opt_fc
= fs_sink_ctf_field_class_as_option(fc
);
1251 field_ref
= opt_fc
->tag_ref
;
1256 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1258 struct fs_sink_ctf_field_class_sequence
*seq_fc
= fs_sink_ctf_field_class_as_sequence(fc
);
1260 field_ref
= seq_fc
->length_ref
;
1261 is_before
= seq_fc
->length_is_before
;
1265 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
1267 struct fs_sink_ctf_field_class_variant
*var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
1269 field_ref
= var_fc
->tag_ref
;
1270 is_before
= var_fc
->tag_is_before
;
1278 BT_ASSERT(field_ref
);
1284 /* Initial field ref */
1285 g_string_printf(field_ref
, "__%s_%s", fc_name
, tgt_type
);
1288 * Make sure field ref does not clash with an existing field
1289 * class name within the same parent structure field class.
1292 bool name_ok
= true;
1294 for (i
= 0; i
< parent_struct_fc
->members
->len
; i
++) {
1295 struct fs_sink_ctf_named_field_class
*named_fc
=
1296 fs_sink_ctf_field_class_struct_borrow_member_by_index(parent_struct_fc
, i
);
1298 if (strcmp(field_ref
->str
, named_fc
->name
->str
) == 0) {
1306 /* No clash: we're done */
1310 /* Append suffix and try again */
1311 g_string_printf(field_ref
, "__%s_%s_%u", fc_name
, tgt_type
, suffix
);
1320 * This function recursively sets field refs of sequence and variant
1321 * field classes when they are immediately before, avoiding name clashes
1322 * with existing field class names.
1324 * It can fail at this point if, for example, a sequence field class of
1325 * which to set the length's field ref has something else than a
1326 * structure field class as its parent: in this case, there's no
1327 * location to place the length field class immediately before the
1328 * sequence field class.
1330 static int set_field_refs(struct fs_sink_ctf_field_class
* const fc
, const char *fc_name
,
1331 struct fs_sink_ctf_field_class
*parent_fc
)
1334 enum fs_sink_ctf_field_class_type fc_type
;
1340 case FS_SINK_CTF_FIELD_CLASS_TYPE_OPTION
:
1342 struct fs_sink_ctf_field_class_option
*opt_fc
= fs_sink_ctf_field_class_as_option(fc
);
1344 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1349 ret
= set_field_refs(opt_fc
->content_fc
, NULL
, fc
);
1356 case FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
:
1357 case FS_SINK_CTF_FIELD_CLASS_TYPE_VARIANT
:
1361 struct fs_sink_ctf_field_class_struct
*struct_fc
= NULL
;
1362 struct fs_sink_ctf_field_class_variant
*var_fc
= NULL
;
1363 struct fs_sink_ctf_named_field_class
*named_fc
;
1365 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1366 struct_fc
= fs_sink_ctf_field_class_as_struct(fc
);
1367 len
= struct_fc
->members
->len
;
1369 var_fc
= fs_sink_ctf_field_class_as_variant(fc
);
1370 len
= var_fc
->options
->len
;
1371 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1377 for (i
= 0; i
< len
; i
++) {
1378 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_STRUCT
) {
1379 named_fc
= fs_sink_ctf_field_class_struct_borrow_member_by_index(struct_fc
, i
);
1381 named_fc
= fs_sink_ctf_field_class_variant_borrow_option_by_index(var_fc
, i
);
1384 ret
= set_field_refs(named_fc
->fc
, named_fc
->name
->str
, fc
);
1392 case FS_SINK_CTF_FIELD_CLASS_TYPE_ARRAY
:
1393 case FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
:
1395 struct fs_sink_ctf_field_class_array_base
*array_base_fc
=
1396 fs_sink_ctf_field_class_as_array_base(fc
);
1398 if (fc_type
== FS_SINK_CTF_FIELD_CLASS_TYPE_SEQUENCE
) {
1399 ret
= set_field_ref(fc
, fc_name
, parent_fc
);
1405 ret
= set_field_refs(array_base_fc
->elem_fc
, NULL
, fc
);
1421 * This function translates a root scope trace IR field class to
1422 * a CTF IR field class.
1424 * The resulting CTF IR field class is written to `*fc` so that it
1425 * exists as the parent object's (stream class or event class) true root
1426 * field class during the recursive translation for resolving purposes.
1427 * This is also why this function creates the empty structure field
1428 * class and then calls translate_structure_field_class_members() to
1431 static int translate_scope_field_class(ctf::sink::TraceIrToCtfIrCtx
*ctx
, bt_field_path_scope scope
,
1432 struct fs_sink_ctf_field_class
**fc
,
1433 const bt_field_class
*ir_fc
)
1441 BT_ASSERT(bt_field_class_get_type(ir_fc
) == BT_FIELD_CLASS_TYPE_STRUCTURE
);
1443 *fc
= &fs_sink_ctf_field_class_struct_create_empty(ir_fc
)->base
;
1445 ctx
->cur_scope
= scope
;
1446 BT_ASSERT(ctx
->cur_path
->len
== 0);
1447 ret
= cur_path_stack_push(ctx
, NULL
, false, ir_fc
, NULL
);
1449 BT_COMP_LOGE("Cannot translate scope structure field class: "
1456 translate_structure_field_class_members(ctx
, fs_sink_ctf_field_class_as_struct(*fc
), ir_fc
);
1458 BT_COMP_LOGE("Cannot translate scope structure field class: "
1464 cur_path_stack_pop(ctx
);
1466 /* Set field refs for preceding targets */
1467 ret
= set_field_refs(*fc
, NULL
, NULL
);
1473 static inline void ctx_init(ctf::sink::TraceIrToCtfIrCtx
*ctx
, struct fs_sink_comp
*fs_sink
)
1475 ctx
->cur_path
= g_array_new(FALSE
, TRUE
, sizeof(struct field_path_elem
));
1476 BT_ASSERT(ctx
->cur_path
);
1477 ctx
->log_level
= fs_sink
->log_level
;
1478 ctx
->self_comp
= fs_sink
->self_comp
;
1481 static inline void ctx_fini(ctf::sink::TraceIrToCtfIrCtx
*ctx
)
1483 if (ctx
->cur_path
) {
1484 g_array_free(ctx
->cur_path
, TRUE
);
1485 ctx
->cur_path
= NULL
;
1489 static int translate_event_class(struct fs_sink_comp
*fs_sink
, struct fs_sink_ctf_stream_class
*sc
,
1490 const bt_event_class
*ir_ec
,
1491 struct fs_sink_ctf_event_class
**out_ec
)
1494 ctf::sink::TraceIrToCtfIrCtx ctx
;
1495 struct fs_sink_ctf_event_class
*ec
;
1500 ctx_init(&ctx
, fs_sink
);
1501 ec
= fs_sink_ctf_event_class_create(sc
, ir_ec
);
1505 ret
= translate_scope_field_class(
1506 &ctx
, BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT
, &ec
->spec_context_fc
,
1507 bt_event_class_borrow_specific_context_field_class_const(ir_ec
));
1512 ret
= translate_scope_field_class(&ctx
, BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD
, &ec
->payload_fc
,
1513 bt_event_class_borrow_payload_field_class_const(ir_ec
));
1524 int try_translate_event_class_trace_ir_to_ctf_ir(struct fs_sink_comp
*fs_sink
,
1525 struct fs_sink_ctf_stream_class
*sc
,
1526 const bt_event_class
*ir_ec
,
1527 struct fs_sink_ctf_event_class
**out_ec
)
1534 /* Check in hash table first */
1535 *out_ec
= (fs_sink_ctf_event_class
*) g_hash_table_lookup(sc
->event_classes_from_ir
, ir_ec
);
1536 if (G_LIKELY(*out_ec
)) {
1540 ret
= translate_event_class(fs_sink
, sc
, ir_ec
, out_ec
);
1546 static bool default_clock_class_name_exists(struct fs_sink_ctf_trace
*trace
, const char *name
)
1548 bool exists
= false;
1551 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1552 struct fs_sink_ctf_stream_class
*sc
=
1553 (fs_sink_ctf_stream_class
*) trace
->stream_classes
->pdata
[i
];
1555 if (sc
->default_clock_class_name
->len
== 0) {
1556 /* No default clock class */
1560 if (strcmp(sc
->default_clock_class_name
->str
, name
) == 0) {
1570 static void make_unique_default_clock_class_name(struct fs_sink_ctf_stream_class
*sc
)
1572 unsigned int suffix
= 0;
1574 std::string name
= "default";
1576 while (default_clock_class_name_exists(sc
->trace
, name
.c_str())) {
1577 name
= "default" + std::to_string(suffix
);
1581 g_string_assign(sc
->default_clock_class_name
, name
.c_str());
1584 static int translate_stream_class(struct fs_sink_comp
*fs_sink
, struct fs_sink_ctf_trace
*trace
,
1585 const bt_stream_class
*ir_sc
,
1586 struct fs_sink_ctf_stream_class
**out_sc
)
1589 ctf::sink::TraceIrToCtfIrCtx ctx
;
1593 ctx_init(&ctx
, fs_sink
);
1594 *out_sc
= fs_sink_ctf_stream_class_create(trace
, ir_sc
);
1597 /* Set default clock class's protected name, if any */
1598 if ((*out_sc
)->default_clock_class
) {
1599 const char *name
= bt_clock_class_get_name((*out_sc
)->default_clock_class
);
1602 /* Try original name, protected */
1603 g_string_assign((*out_sc
)->default_clock_class_name
, "");
1605 if (must_protect_identifier(name
)) {
1606 g_string_assign((*out_sc
)->default_clock_class_name
, "_");
1609 g_string_assign((*out_sc
)->default_clock_class_name
, name
);
1610 if (!ist_valid_identifier((*out_sc
)->default_clock_class_name
->str
)) {
1611 /* Invalid: create a new name */
1612 make_unique_default_clock_class_name(*out_sc
);
1615 /* No name: create a name */
1616 make_unique_default_clock_class_name(*out_sc
);
1620 ctx
.cur_sc
= *out_sc
;
1621 ret
= translate_scope_field_class(
1622 &ctx
, BT_FIELD_PATH_SCOPE_PACKET_CONTEXT
, &(*out_sc
)->packet_context_fc
,
1623 bt_stream_class_borrow_packet_context_field_class_const(ir_sc
));
1628 if ((*out_sc
)->packet_context_fc
) {
1630 * Make sure the structure field class's alignment is
1631 * enough: 8 is what we use for our own special members
1632 * in the packet context.
1634 fs_sink_ctf_field_class_struct_align_at_least(
1635 fs_sink_ctf_field_class_as_struct((*out_sc
)->packet_context_fc
), 8);
1638 ret
= translate_scope_field_class(
1639 &ctx
, BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT
, &(*out_sc
)->event_common_context_fc
,
1640 bt_stream_class_borrow_event_common_context_field_class_const(ir_sc
));
1648 fs_sink_ctf_stream_class_destroy(*out_sc
);
1656 int try_translate_stream_class_trace_ir_to_ctf_ir(struct fs_sink_comp
*fs_sink
,
1657 struct fs_sink_ctf_trace
*trace
,
1658 const bt_stream_class
*ir_sc
,
1659 struct fs_sink_ctf_stream_class
**out_sc
)
1667 for (i
= 0; i
< trace
->stream_classes
->len
; i
++) {
1668 *out_sc
= (fs_sink_ctf_stream_class
*) trace
->stream_classes
->pdata
[i
];
1670 if ((*out_sc
)->ir_sc
== ir_sc
) {
1675 ret
= translate_stream_class(fs_sink
, trace
, ir_sc
, out_sc
);
1681 struct fs_sink_ctf_trace
*translate_trace_trace_ir_to_ctf_ir(struct fs_sink_comp
*fs_sink
,
1682 const bt_trace
*ir_trace
)
1686 struct fs_sink_ctf_trace
*trace
= NULL
;
1688 /* Check that trace's environment is TSDL-compatible */
1689 count
= bt_trace_get_environment_entry_count(ir_trace
);
1690 for (i
= 0; i
< count
; i
++) {
1692 const bt_value
*val
;
1694 bt_trace_borrow_environment_entry_by_index_const(ir_trace
, i
, &name
, &val
);
1696 if (!ist_valid_identifier(name
)) {
1697 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
, fs_sink
->self_comp
,
1698 "Unsupported trace class's environment entry name: "
1704 switch (bt_value_get_type(val
)) {
1705 case BT_VALUE_TYPE_SIGNED_INTEGER
:
1706 case BT_VALUE_TYPE_STRING
:
1709 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, fs_sink
->log_level
, fs_sink
->self_comp
,
1710 "Unsupported trace class's environment entry value type: "
1712 bt_common_value_type_string(bt_value_get_type(val
)));
1717 trace
= fs_sink_ctf_trace_create(ir_trace
);