2 * SPDX-License-Identifier: MIT
4 * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
7 #include <babeltrace2/babeltrace.h>
8 #include "common/macros.h"
9 #include "common/assert.h"
16 #include "ctf-meta-visitors.hpp"
19 bt_self_component
*self_comp
;
20 bt_trace_class
*ir_tc
;
21 bt_stream_class
*ir_sc
;
22 struct ctf_trace_class
*tc
;
23 struct ctf_stream_class
*sc
;
24 struct ctf_event_class
*ec
;
29 bt_field_class
*ctf_field_class_to_ir(struct ctx
*ctx
,
30 struct ctf_field_class
*fc
);
33 void ctf_field_class_int_set_props(struct ctf_field_class_int
*fc
,
34 bt_field_class
*ir_fc
)
36 bt_field_class_integer_set_field_value_range(ir_fc
,
38 bt_field_class_integer_set_preferred_display_base(ir_fc
,
43 bt_field_class
*ctf_field_class_int_to_ir(struct ctx
*ctx
,
44 struct ctf_field_class_int
*fc
)
46 bt_field_class
*ir_fc
;
49 ir_fc
= bt_field_class_integer_signed_create(ctx
->ir_tc
);
51 ir_fc
= bt_field_class_integer_unsigned_create(ctx
->ir_tc
);
55 ctf_field_class_int_set_props(fc
, ir_fc
);
60 bt_field_class
*ctf_field_class_enum_to_ir(struct ctx
*ctx
,
61 struct ctf_field_class_enum
*fc
)
64 bt_field_class
*ir_fc
;
67 if (fc
->base
.is_signed
) {
68 ir_fc
= bt_field_class_enumeration_signed_create(ctx
->ir_tc
);
70 ir_fc
= bt_field_class_enumeration_unsigned_create(ctx
->ir_tc
);
74 ctf_field_class_int_set_props(&fc
->base
, ir_fc
);
76 for (i
= 0; i
< fc
->mappings
->len
; i
++) {
77 struct ctf_field_class_enum_mapping
*mapping
=
78 ctf_field_class_enum_borrow_mapping_by_index(fc
, i
);
79 bt_integer_range_set_signed
*range_set_signed
= NULL
;
80 bt_integer_range_set_unsigned
*range_set_unsigned
= NULL
;
83 if (fc
->base
.is_signed
) {
84 range_set_signed
= bt_integer_range_set_signed_create();
85 BT_ASSERT(range_set_signed
);
87 range_set_unsigned
= bt_integer_range_set_unsigned_create();
88 BT_ASSERT(range_set_unsigned
);
91 for (range_i
= 0; range_i
< mapping
->ranges
->len
; range_i
++) {
92 struct ctf_range
*range
=
93 ctf_field_class_enum_mapping_borrow_range_by_index(
96 if (fc
->base
.is_signed
) {
97 ret
= bt_integer_range_set_signed_add_range(
98 range_set_signed
, range
->lower
.i
,
101 ret
= bt_integer_range_set_unsigned_add_range(
102 range_set_unsigned
, range
->lower
.u
,
109 if (fc
->base
.is_signed
) {
110 ret
= bt_field_class_enumeration_signed_add_mapping(
111 ir_fc
, mapping
->label
->str
, range_set_signed
);
112 BT_INTEGER_RANGE_SET_SIGNED_PUT_REF_AND_RESET(range_set_signed
);
114 ret
= bt_field_class_enumeration_unsigned_add_mapping(
115 ir_fc
, mapping
->label
->str
, range_set_unsigned
);
116 BT_INTEGER_RANGE_SET_UNSIGNED_PUT_REF_AND_RESET(range_set_unsigned
);
126 bt_field_class
*ctf_field_class_float_to_ir(struct ctx
*ctx
,
127 struct ctf_field_class_float
*fc
)
129 bt_field_class
*ir_fc
;
131 if (fc
->base
.size
== 32) {
132 ir_fc
= bt_field_class_real_single_precision_create(ctx
->ir_tc
);
134 ir_fc
= bt_field_class_real_double_precision_create(ctx
->ir_tc
);
142 bt_field_class
*ctf_field_class_string_to_ir(struct ctx
*ctx
,
143 struct ctf_field_class_string
*fc
)
145 bt_field_class
*ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
152 void translate_struct_field_class_members(struct ctx
*ctx
,
153 struct ctf_field_class_struct
*fc
, bt_field_class
*ir_fc
,
154 bool with_header_prefix
,
155 struct ctf_field_class_struct
*context_fc
)
160 for (i
= 0; i
< fc
->members
->len
; i
++) {
161 struct ctf_named_field_class
*named_fc
=
162 ctf_field_class_struct_borrow_member_by_index(fc
, i
);
163 bt_field_class
*member_ir_fc
;
164 const char *name
= named_fc
->name
->str
;
166 if (!named_fc
->fc
->in_ir
) {
170 member_ir_fc
= ctf_field_class_to_ir(ctx
, named_fc
->fc
);
171 BT_ASSERT(member_ir_fc
);
172 ret
= bt_field_class_structure_append_member(ir_fc
, name
,
175 bt_field_class_put_ref(member_ir_fc
);
180 bt_field_class
*ctf_field_class_struct_to_ir(struct ctx
*ctx
,
181 struct ctf_field_class_struct
*fc
)
183 bt_field_class
*ir_fc
= bt_field_class_structure_create(ctx
->ir_tc
);
186 translate_struct_field_class_members(ctx
, fc
, ir_fc
, false, NULL
);
191 bt_field_class
*borrow_ir_fc_from_field_path(struct ctx
*ctx
,
192 struct ctf_field_path
*field_path
)
194 bt_field_class
*ir_fc
= NULL
;
195 struct ctf_field_class
*fc
= ctf_field_path_borrow_field_class(
196 field_path
, ctx
->tc
, ctx
->sc
, ctx
->ec
);
208 const bt_field_class_enumeration_mapping
*find_ir_enum_field_class_mapping_by_label(
209 const bt_field_class
*fc
, const char *label
, bool is_signed
)
211 const bt_field_class_enumeration_mapping
*mapping
= NULL
;
214 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(fc
); i
++) {
215 const bt_field_class_enumeration_mapping
*this_mapping
;
216 const bt_field_class_enumeration_signed_mapping
*signed_this_mapping
= NULL
;
217 const bt_field_class_enumeration_unsigned_mapping
*unsigned_this_mapping
= NULL
;
220 signed_this_mapping
=
221 bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
223 BT_ASSERT(signed_this_mapping
);
225 bt_field_class_enumeration_signed_mapping_as_mapping_const(
226 signed_this_mapping
);
228 unsigned_this_mapping
=
229 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
231 BT_ASSERT(unsigned_this_mapping
);
233 bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
234 unsigned_this_mapping
);
237 BT_ASSERT(this_mapping
);
239 if (strcmp(bt_field_class_enumeration_mapping_get_label(
240 this_mapping
), label
) == 0) {
241 mapping
= this_mapping
;
251 bt_field_class
*ctf_field_class_variant_to_ir(struct ctx
*ctx
,
252 struct ctf_field_class_variant
*fc
)
255 bt_field_class
*ir_fc
;
257 bt_field_class
*ir_tag_fc
= NULL
;
259 if (fc
->tag_path
.root
!= CTF_SCOPE_PACKET_HEADER
&&
260 fc
->tag_path
.root
!= CTF_SCOPE_EVENT_HEADER
) {
261 ir_tag_fc
= borrow_ir_fc_from_field_path(ctx
, &fc
->tag_path
);
262 BT_ASSERT(ir_tag_fc
);
265 ir_fc
= bt_field_class_variant_create(ctx
->ir_tc
, ir_tag_fc
);
268 for (i
= 0; i
< fc
->options
->len
; i
++) {
269 struct ctf_named_field_class
*named_fc
=
270 ctf_field_class_variant_borrow_option_by_index(fc
, i
);
271 bt_field_class
*option_ir_fc
;
273 BT_ASSERT(named_fc
->fc
->in_ir
);
274 option_ir_fc
= ctf_field_class_to_ir(ctx
, named_fc
->fc
);
275 BT_ASSERT(option_ir_fc
);
279 * At this point the trace IR selector
280 * (enumeration) field class already exists if
281 * the variant is tagged (`ir_tag_fc`). This one
282 * already contains range sets for its mappings,
283 * so we just reuse the same, finding them by
284 * matching a variant field class's option's
285 * _original_ name (with a leading underscore,
286 * possibly) with a selector field class's
289 if (fc
->tag_fc
->base
.is_signed
) {
290 const bt_field_class_enumeration_signed_mapping
*mapping
=
291 (bt_field_class_enumeration_signed_mapping
*)
292 find_ir_enum_field_class_mapping_by_label(
294 named_fc
->orig_name
->str
, true);
295 const bt_integer_range_set_signed
*range_set
;
299 bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
301 BT_ASSERT(range_set
);
302 ret
= bt_field_class_variant_with_selector_field_integer_signed_append_option(
303 ir_fc
, named_fc
->name
->str
,
304 option_ir_fc
, range_set
);
306 const bt_field_class_enumeration_unsigned_mapping
*mapping
=
307 (bt_field_class_enumeration_unsigned_mapping
*)
308 find_ir_enum_field_class_mapping_by_label(
310 named_fc
->orig_name
->str
,
312 const bt_integer_range_set_unsigned
*range_set
;
316 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
318 BT_ASSERT(range_set
);
319 ret
= bt_field_class_variant_with_selector_field_integer_unsigned_append_option(
320 ir_fc
, named_fc
->name
->str
,
321 option_ir_fc
, range_set
);
324 ret
= bt_field_class_variant_without_selector_append_option(
325 ir_fc
, named_fc
->name
->str
, option_ir_fc
);
329 bt_field_class_put_ref(option_ir_fc
);
336 bt_field_class
*ctf_field_class_array_to_ir(struct ctx
*ctx
,
337 struct ctf_field_class_array
*fc
)
339 bt_field_class
*ir_fc
;
340 bt_field_class
*elem_ir_fc
;
342 if (fc
->base
.is_text
) {
343 ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
348 elem_ir_fc
= ctf_field_class_to_ir(ctx
, fc
->base
.elem_fc
);
349 BT_ASSERT(elem_ir_fc
);
350 ir_fc
= bt_field_class_array_static_create(ctx
->ir_tc
, elem_ir_fc
,
353 bt_field_class_put_ref(elem_ir_fc
);
360 bt_field_class
*ctf_field_class_sequence_to_ir(struct ctx
*ctx
,
361 struct ctf_field_class_sequence
*fc
)
363 bt_field_class
*ir_fc
;
364 bt_field_class
*elem_ir_fc
;
365 bt_field_class
*length_fc
= NULL
;
367 if (fc
->base
.is_text
) {
368 ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
373 elem_ir_fc
= ctf_field_class_to_ir(ctx
, fc
->base
.elem_fc
);
374 BT_ASSERT(elem_ir_fc
);
376 if (fc
->length_path
.root
!= CTF_SCOPE_PACKET_HEADER
&&
377 fc
->length_path
.root
!= CTF_SCOPE_EVENT_HEADER
) {
378 length_fc
= borrow_ir_fc_from_field_path(ctx
, &fc
->length_path
);
379 BT_ASSERT(length_fc
);
382 ir_fc
= bt_field_class_array_dynamic_create(ctx
->ir_tc
, elem_ir_fc
,
385 bt_field_class_put_ref(elem_ir_fc
);
393 bt_field_class
*ctf_field_class_to_ir(struct ctx
*ctx
,
394 struct ctf_field_class
*fc
)
396 bt_field_class
*ir_fc
= NULL
;
399 BT_ASSERT(fc
->in_ir
);
402 case CTF_FIELD_CLASS_TYPE_INT
:
403 ir_fc
= ctf_field_class_int_to_ir(ctx
, ctf_field_class_as_int(fc
));
405 case CTF_FIELD_CLASS_TYPE_ENUM
:
406 ir_fc
= ctf_field_class_enum_to_ir(ctx
, ctf_field_class_as_enum(fc
));
408 case CTF_FIELD_CLASS_TYPE_FLOAT
:
409 ir_fc
= ctf_field_class_float_to_ir(ctx
, ctf_field_class_as_float(fc
));
411 case CTF_FIELD_CLASS_TYPE_STRING
:
412 ir_fc
= ctf_field_class_string_to_ir(ctx
, ctf_field_class_as_string(fc
));
414 case CTF_FIELD_CLASS_TYPE_STRUCT
:
415 ir_fc
= ctf_field_class_struct_to_ir(ctx
, ctf_field_class_as_struct(fc
));
417 case CTF_FIELD_CLASS_TYPE_ARRAY
:
418 ir_fc
= ctf_field_class_array_to_ir(ctx
, ctf_field_class_as_array(fc
));
420 case CTF_FIELD_CLASS_TYPE_SEQUENCE
:
421 ir_fc
= ctf_field_class_sequence_to_ir(ctx
, ctf_field_class_as_sequence(fc
));
423 case CTF_FIELD_CLASS_TYPE_VARIANT
:
424 ir_fc
= ctf_field_class_variant_to_ir(ctx
, ctf_field_class_as_variant(fc
));
435 bool ctf_field_class_struct_has_immediate_member_in_ir(
436 struct ctf_field_class_struct
*fc
)
439 bool has_immediate_member_in_ir
= false;
442 * If the structure field class has no members at all, then it
443 * was an empty structure in the beginning, so leave it existing
446 if (fc
->members
->len
== 0) {
447 has_immediate_member_in_ir
= true;
451 for (i
= 0; i
< fc
->members
->len
; i
++) {
452 struct ctf_named_field_class
*named_fc
=
453 ctf_field_class_struct_borrow_member_by_index(fc
, i
);
455 if (named_fc
->fc
->in_ir
) {
456 has_immediate_member_in_ir
= true;
462 return has_immediate_member_in_ir
;
466 bt_field_class
*scope_ctf_field_class_to_ir(struct ctx
*ctx
)
468 bt_field_class
*ir_fc
= NULL
;
469 struct ctf_field_class
*fc
= NULL
;
471 switch (ctx
->scope
) {
472 case CTF_SCOPE_PACKET_CONTEXT
:
473 fc
= ctx
->sc
->packet_context_fc
;
475 case CTF_SCOPE_EVENT_COMMON_CONTEXT
:
476 fc
= ctx
->sc
->event_common_context_fc
;
478 case CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
:
479 fc
= ctx
->ec
->spec_context_fc
;
481 case CTF_SCOPE_EVENT_PAYLOAD
:
482 fc
= ctx
->ec
->payload_fc
;
488 if (fc
&& ctf_field_class_struct_has_immediate_member_in_ir(
489 ctf_field_class_as_struct(fc
))) {
490 ir_fc
= ctf_field_class_to_ir(ctx
, fc
);
497 void ctf_event_class_to_ir(struct ctx
*ctx
)
500 bt_event_class
*ir_ec
= NULL
;
501 bt_field_class
*ir_fc
;
505 if (ctx
->ec
->is_translated
) {
506 ir_ec
= bt_stream_class_borrow_event_class_by_id(
507 ctx
->ir_sc
, ctx
->ec
->id
);
512 ir_ec
= bt_event_class_create_with_id(ctx
->ir_sc
, ctx
->ec
->id
);
514 bt_event_class_put_ref(ir_ec
);
515 ctx
->scope
= CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
;
516 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
518 ret
= bt_event_class_set_specific_context_field_class(
521 bt_field_class_put_ref(ir_fc
);
524 ctx
->scope
= CTF_SCOPE_EVENT_PAYLOAD
;
525 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
527 ret
= bt_event_class_set_payload_field_class(ir_ec
,
530 bt_field_class_put_ref(ir_fc
);
533 if (ctx
->ec
->name
->len
> 0) {
534 ret
= bt_event_class_set_name(ir_ec
, ctx
->ec
->name
->str
);
538 if (ctx
->ec
->emf_uri
->len
> 0) {
539 ret
= bt_event_class_set_emf_uri(ir_ec
, ctx
->ec
->emf_uri
->str
);
543 if (ctx
->ec
->is_log_level_set
) {
544 bt_event_class_set_log_level(ir_ec
, ctx
->ec
->log_level
);
547 ctx
->ec
->is_translated
= true;
548 ctx
->ec
->ir_ec
= ir_ec
;
556 void ctf_stream_class_to_ir(struct ctx
*ctx
)
559 bt_field_class
*ir_fc
;
563 if (ctx
->sc
->is_translated
) {
564 ctx
->ir_sc
= bt_trace_class_borrow_stream_class_by_id(
565 ctx
->ir_tc
, ctx
->sc
->id
);
566 BT_ASSERT(ctx
->ir_sc
);
570 ctx
->ir_sc
= bt_stream_class_create_with_id(ctx
->ir_tc
, ctx
->sc
->id
);
571 BT_ASSERT(ctx
->ir_sc
);
572 bt_stream_class_put_ref(ctx
->ir_sc
);
574 if (ctx
->sc
->default_clock_class
) {
575 BT_ASSERT(ctx
->sc
->default_clock_class
->ir_cc
);
576 ret
= bt_stream_class_set_default_clock_class(ctx
->ir_sc
,
577 ctx
->sc
->default_clock_class
->ir_cc
);
581 bt_stream_class_set_supports_packets(ctx
->ir_sc
, BT_TRUE
,
582 ctx
->sc
->packets_have_ts_begin
, ctx
->sc
->packets_have_ts_end
);
583 bt_stream_class_set_supports_discarded_events(ctx
->ir_sc
,
584 ctx
->sc
->has_discarded_events
,
585 ctx
->sc
->discarded_events_have_default_cs
);
586 bt_stream_class_set_supports_discarded_packets(ctx
->ir_sc
,
587 ctx
->sc
->has_discarded_packets
,
588 ctx
->sc
->discarded_packets_have_default_cs
);
589 ctx
->scope
= CTF_SCOPE_PACKET_CONTEXT
;
590 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
592 ret
= bt_stream_class_set_packet_context_field_class(
595 bt_field_class_put_ref(ir_fc
);
598 ctx
->scope
= CTF_SCOPE_EVENT_COMMON_CONTEXT
;
599 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
601 ret
= bt_stream_class_set_event_common_context_field_class(
604 bt_field_class_put_ref(ir_fc
);
607 bt_stream_class_set_assigns_automatic_event_class_id(ctx
->ir_sc
,
609 bt_stream_class_set_assigns_automatic_stream_id(ctx
->ir_sc
, BT_FALSE
);
611 ctx
->sc
->is_translated
= true;
612 ctx
->sc
->ir_sc
= ctx
->ir_sc
;
619 void ctf_clock_class_to_ir(bt_clock_class
*ir_cc
, struct ctf_clock_class
*cc
)
623 if (strlen(cc
->name
->str
) > 0) {
624 ret
= bt_clock_class_set_name(ir_cc
, cc
->name
->str
);
628 if (strlen(cc
->description
->str
) > 0) {
629 ret
= bt_clock_class_set_description(ir_cc
, cc
->description
->str
);
633 bt_clock_class_set_frequency(ir_cc
, cc
->frequency
);
634 bt_clock_class_set_precision(ir_cc
, cc
->precision
);
635 bt_clock_class_set_offset(ir_cc
, cc
->offset_seconds
, cc
->offset_cycles
);
638 bt_clock_class_set_uuid(ir_cc
, cc
->uuid
);
641 bt_clock_class_set_origin_is_unix_epoch(ir_cc
, cc
->is_absolute
);
645 int ctf_trace_class_to_ir(struct ctx
*ctx
)
651 BT_ASSERT(ctx
->ir_tc
);
653 if (ctx
->tc
->is_translated
) {
657 for (i
= 0; i
< ctx
->tc
->clock_classes
->len
; i
++) {
658 ctf_clock_class
*cc
= (ctf_clock_class
*) ctx
->tc
->clock_classes
->pdata
[i
];
660 cc
->ir_cc
= bt_clock_class_create(ctx
->self_comp
);
661 ctf_clock_class_to_ir(cc
->ir_cc
, cc
);
664 bt_trace_class_set_assigns_automatic_stream_class_id(ctx
->ir_tc
,
666 ctx
->tc
->is_translated
= true;
667 ctx
->tc
->ir_tc
= ctx
->ir_tc
;
674 int ctf_trace_class_translate(bt_self_component
*self_comp
,
675 bt_trace_class
*ir_tc
, struct ctf_trace_class
*tc
)
679 struct ctx ctx
= { 0 };
681 ctx
.self_comp
= self_comp
;
684 ret
= ctf_trace_class_to_ir(&ctx
);
689 for (i
= 0; i
< tc
->stream_classes
->len
; i
++) {
691 ctx
.sc
= (ctf_stream_class
*) tc
->stream_classes
->pdata
[i
];
693 ctf_stream_class_to_ir(&ctx
);
695 for (j
= 0; j
< ctx
.sc
->event_classes
->len
; j
++) {
696 ctx
.ec
= (ctf_event_class
*) ctx
.sc
->event_classes
->pdata
[j
];
698 ctf_event_class_to_ir(&ctx
);