2 * SPDX-License-Identifier: MIT
4 * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
10 #include <babeltrace2/babeltrace.h>
12 #include "common/assert.h"
14 #include "ctf-meta-visitors.hpp"
18 struct MetaTranslateCtx
20 bt_self_component
*self_comp
;
21 bt_trace_class
*ir_tc
;
22 bt_stream_class
*ir_sc
;
23 struct ctf_trace_class
*tc
;
24 struct ctf_stream_class
*sc
;
25 struct ctf_event_class
*ec
;
31 static inline bt_field_class
*ctf_field_class_to_ir(ctf::MetaTranslateCtx
*ctx
,
32 struct ctf_field_class
*fc
);
34 static inline void ctf_field_class_int_set_props(struct ctf_field_class_int
*fc
,
35 bt_field_class
*ir_fc
)
37 bt_field_class_integer_set_field_value_range(ir_fc
, fc
->base
.size
);
38 bt_field_class_integer_set_preferred_display_base(ir_fc
, fc
->disp_base
);
41 static inline bt_field_class
*ctf_field_class_int_to_ir(ctf::MetaTranslateCtx
*ctx
,
42 struct ctf_field_class_int
*fc
)
44 bt_field_class
*ir_fc
;
47 ir_fc
= bt_field_class_integer_signed_create(ctx
->ir_tc
);
49 ir_fc
= bt_field_class_integer_unsigned_create(ctx
->ir_tc
);
53 ctf_field_class_int_set_props(fc
, ir_fc
);
57 static inline bt_field_class
*ctf_field_class_enum_to_ir(ctf::MetaTranslateCtx
*ctx
,
58 struct ctf_field_class_enum
*fc
)
61 bt_field_class
*ir_fc
;
64 if (fc
->base
.is_signed
) {
65 ir_fc
= bt_field_class_enumeration_signed_create(ctx
->ir_tc
);
67 ir_fc
= bt_field_class_enumeration_unsigned_create(ctx
->ir_tc
);
71 ctf_field_class_int_set_props(&fc
->base
, ir_fc
);
73 for (i
= 0; i
< fc
->mappings
->len
; i
++) {
74 struct ctf_field_class_enum_mapping
*mapping
=
75 ctf_field_class_enum_borrow_mapping_by_index(fc
, i
);
76 bt_integer_range_set_signed
*range_set_signed
= NULL
;
77 bt_integer_range_set_unsigned
*range_set_unsigned
= NULL
;
80 if (fc
->base
.is_signed
) {
81 range_set_signed
= bt_integer_range_set_signed_create();
82 BT_ASSERT(range_set_signed
);
84 range_set_unsigned
= bt_integer_range_set_unsigned_create();
85 BT_ASSERT(range_set_unsigned
);
88 for (range_i
= 0; range_i
< mapping
->ranges
->len
; range_i
++) {
89 struct ctf_range
*range
=
90 ctf_field_class_enum_mapping_borrow_range_by_index(mapping
, range_i
);
92 if (fc
->base
.is_signed
) {
93 ret
= bt_integer_range_set_signed_add_range(range_set_signed
, range
->lower
.i
,
96 ret
= bt_integer_range_set_unsigned_add_range(range_set_unsigned
, range
->lower
.u
,
103 if (fc
->base
.is_signed
) {
104 ret
= bt_field_class_enumeration_signed_add_mapping(ir_fc
, mapping
->label
->str
,
106 BT_INTEGER_RANGE_SET_SIGNED_PUT_REF_AND_RESET(range_set_signed
);
108 ret
= bt_field_class_enumeration_unsigned_add_mapping(ir_fc
, mapping
->label
->str
,
110 BT_INTEGER_RANGE_SET_UNSIGNED_PUT_REF_AND_RESET(range_set_unsigned
);
119 static inline bt_field_class
*ctf_field_class_float_to_ir(ctf::MetaTranslateCtx
*ctx
,
120 struct ctf_field_class_float
*fc
)
122 bt_field_class
*ir_fc
;
124 if (fc
->base
.size
== 32) {
125 ir_fc
= bt_field_class_real_single_precision_create(ctx
->ir_tc
);
127 ir_fc
= bt_field_class_real_double_precision_create(ctx
->ir_tc
);
134 static inline bt_field_class
*ctf_field_class_string_to_ir(ctf::MetaTranslateCtx
*ctx
)
136 bt_field_class
*ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
142 static inline void translate_struct_field_class_members(ctf::MetaTranslateCtx
*ctx
,
143 struct ctf_field_class_struct
*fc
,
144 bt_field_class
*ir_fc
, bool,
145 struct ctf_field_class_struct
*)
150 for (i
= 0; i
< fc
->members
->len
; i
++) {
151 struct ctf_named_field_class
*named_fc
=
152 ctf_field_class_struct_borrow_member_by_index(fc
, i
);
153 bt_field_class
*member_ir_fc
;
154 const char *name
= named_fc
->name
->str
;
156 if (!named_fc
->fc
->in_ir
) {
160 member_ir_fc
= ctf_field_class_to_ir(ctx
, named_fc
->fc
);
161 BT_ASSERT(member_ir_fc
);
162 ret
= bt_field_class_structure_append_member(ir_fc
, name
, member_ir_fc
);
164 bt_field_class_put_ref(member_ir_fc
);
168 static inline bt_field_class
*ctf_field_class_struct_to_ir(ctf::MetaTranslateCtx
*ctx
,
169 struct ctf_field_class_struct
*fc
)
171 bt_field_class
*ir_fc
= bt_field_class_structure_create(ctx
->ir_tc
);
174 translate_struct_field_class_members(ctx
, fc
, ir_fc
, false, NULL
);
178 static inline bt_field_class
*borrow_ir_fc_from_field_path(ctf::MetaTranslateCtx
*ctx
,
179 struct ctf_field_path
*field_path
)
181 bt_field_class
*ir_fc
= NULL
;
182 struct ctf_field_class
*fc
=
183 ctf_field_path_borrow_field_class(field_path
, ctx
->tc
, ctx
->sc
, ctx
->ec
);
194 static inline const bt_field_class_enumeration_mapping
*
195 find_ir_enum_field_class_mapping_by_label(const bt_field_class
*fc
, const char *label
,
198 const bt_field_class_enumeration_mapping
*mapping
= NULL
;
201 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(fc
); i
++) {
202 const bt_field_class_enumeration_mapping
*this_mapping
;
203 const bt_field_class_enumeration_signed_mapping
*signed_this_mapping
= NULL
;
204 const bt_field_class_enumeration_unsigned_mapping
*unsigned_this_mapping
= NULL
;
207 signed_this_mapping
=
208 bt_field_class_enumeration_signed_borrow_mapping_by_index_const(fc
, i
);
209 BT_ASSERT(signed_this_mapping
);
211 bt_field_class_enumeration_signed_mapping_as_mapping_const(signed_this_mapping
);
213 unsigned_this_mapping
=
214 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(fc
, i
);
215 BT_ASSERT(unsigned_this_mapping
);
217 bt_field_class_enumeration_unsigned_mapping_as_mapping_const(unsigned_this_mapping
);
220 BT_ASSERT(this_mapping
);
222 if (strcmp(bt_field_class_enumeration_mapping_get_label(this_mapping
), label
) == 0) {
223 mapping
= this_mapping
;
232 static inline bt_field_class
*ctf_field_class_variant_to_ir(ctf::MetaTranslateCtx
*ctx
,
233 struct ctf_field_class_variant
*fc
)
236 bt_field_class
*ir_fc
;
238 bt_field_class
*ir_tag_fc
= NULL
;
240 if (fc
->tag_path
.root
!= CTF_SCOPE_PACKET_HEADER
&&
241 fc
->tag_path
.root
!= CTF_SCOPE_EVENT_HEADER
) {
242 ir_tag_fc
= borrow_ir_fc_from_field_path(ctx
, &fc
->tag_path
);
243 BT_ASSERT(ir_tag_fc
);
246 ir_fc
= bt_field_class_variant_create(ctx
->ir_tc
, ir_tag_fc
);
249 for (i
= 0; i
< fc
->options
->len
; i
++) {
250 struct ctf_named_field_class
*named_fc
=
251 ctf_field_class_variant_borrow_option_by_index(fc
, i
);
252 bt_field_class
*option_ir_fc
;
254 BT_ASSERT(named_fc
->fc
->in_ir
);
255 option_ir_fc
= ctf_field_class_to_ir(ctx
, named_fc
->fc
);
256 BT_ASSERT(option_ir_fc
);
260 * At this point the trace IR selector
261 * (enumeration) field class already exists if
262 * the variant is tagged (`ir_tag_fc`). This one
263 * already contains range sets for its mappings,
264 * so we just reuse the same, finding them by
265 * matching a variant field class's option's
266 * _original_ name (with a leading underscore,
267 * possibly) with a selector field class's
270 if (fc
->tag_fc
->base
.is_signed
) {
271 const bt_field_class_enumeration_signed_mapping
*mapping
=
272 (bt_field_class_enumeration_signed_mapping
*)
273 find_ir_enum_field_class_mapping_by_label(ir_tag_fc
,
274 named_fc
->orig_name
->str
, true);
275 const bt_integer_range_set_signed
*range_set
;
278 range_set
= bt_field_class_enumeration_signed_mapping_borrow_ranges_const(mapping
);
279 BT_ASSERT(range_set
);
280 ret
= bt_field_class_variant_with_selector_field_integer_signed_append_option(
281 ir_fc
, named_fc
->name
->str
, option_ir_fc
, range_set
);
283 const bt_field_class_enumeration_unsigned_mapping
*mapping
=
284 (bt_field_class_enumeration_unsigned_mapping
*)
285 find_ir_enum_field_class_mapping_by_label(ir_tag_fc
,
286 named_fc
->orig_name
->str
, false);
287 const bt_integer_range_set_unsigned
*range_set
;
291 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(mapping
);
292 BT_ASSERT(range_set
);
293 ret
= bt_field_class_variant_with_selector_field_integer_unsigned_append_option(
294 ir_fc
, named_fc
->name
->str
, option_ir_fc
, range_set
);
297 ret
= bt_field_class_variant_without_selector_append_option(ir_fc
, named_fc
->name
->str
,
302 bt_field_class_put_ref(option_ir_fc
);
308 static inline bt_field_class
*ctf_field_class_array_to_ir(ctf::MetaTranslateCtx
*ctx
,
309 struct ctf_field_class_array
*fc
)
311 bt_field_class
*ir_fc
;
312 bt_field_class
*elem_ir_fc
;
314 if (fc
->base
.is_text
) {
315 ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
320 elem_ir_fc
= ctf_field_class_to_ir(ctx
, fc
->base
.elem_fc
);
321 BT_ASSERT(elem_ir_fc
);
322 ir_fc
= bt_field_class_array_static_create(ctx
->ir_tc
, elem_ir_fc
, fc
->length
);
324 bt_field_class_put_ref(elem_ir_fc
);
330 static inline bt_field_class
*ctf_field_class_sequence_to_ir(ctf::MetaTranslateCtx
*ctx
,
331 struct ctf_field_class_sequence
*fc
)
333 bt_field_class
*ir_fc
;
334 bt_field_class
*elem_ir_fc
;
335 bt_field_class
*length_fc
= NULL
;
337 if (fc
->base
.is_text
) {
338 ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
343 elem_ir_fc
= ctf_field_class_to_ir(ctx
, fc
->base
.elem_fc
);
344 BT_ASSERT(elem_ir_fc
);
346 if (fc
->length_path
.root
!= CTF_SCOPE_PACKET_HEADER
&&
347 fc
->length_path
.root
!= CTF_SCOPE_EVENT_HEADER
) {
348 length_fc
= borrow_ir_fc_from_field_path(ctx
, &fc
->length_path
);
349 BT_ASSERT(length_fc
);
352 ir_fc
= bt_field_class_array_dynamic_create(ctx
->ir_tc
, elem_ir_fc
, length_fc
);
354 bt_field_class_put_ref(elem_ir_fc
);
361 static inline bt_field_class
*ctf_field_class_to_ir(ctf::MetaTranslateCtx
*ctx
,
362 struct ctf_field_class
*fc
)
364 bt_field_class
*ir_fc
= NULL
;
367 BT_ASSERT(fc
->in_ir
);
370 case CTF_FIELD_CLASS_TYPE_INT
:
371 ir_fc
= ctf_field_class_int_to_ir(ctx
, ctf_field_class_as_int(fc
));
373 case CTF_FIELD_CLASS_TYPE_ENUM
:
374 ir_fc
= ctf_field_class_enum_to_ir(ctx
, ctf_field_class_as_enum(fc
));
376 case CTF_FIELD_CLASS_TYPE_FLOAT
:
377 ir_fc
= ctf_field_class_float_to_ir(ctx
, ctf_field_class_as_float(fc
));
379 case CTF_FIELD_CLASS_TYPE_STRING
:
380 ir_fc
= ctf_field_class_string_to_ir(ctx
);
382 case CTF_FIELD_CLASS_TYPE_STRUCT
:
383 ir_fc
= ctf_field_class_struct_to_ir(ctx
, ctf_field_class_as_struct(fc
));
385 case CTF_FIELD_CLASS_TYPE_ARRAY
:
386 ir_fc
= ctf_field_class_array_to_ir(ctx
, ctf_field_class_as_array(fc
));
388 case CTF_FIELD_CLASS_TYPE_SEQUENCE
:
389 ir_fc
= ctf_field_class_sequence_to_ir(ctx
, ctf_field_class_as_sequence(fc
));
391 case CTF_FIELD_CLASS_TYPE_VARIANT
:
392 ir_fc
= ctf_field_class_variant_to_ir(ctx
, ctf_field_class_as_variant(fc
));
403 ctf_field_class_struct_has_immediate_member_in_ir(struct ctf_field_class_struct
*fc
)
406 bool has_immediate_member_in_ir
= false;
409 * If the structure field class has no members at all, then it
410 * was an empty structure in the beginning, so leave it existing
413 if (fc
->members
->len
== 0) {
414 has_immediate_member_in_ir
= true;
418 for (i
= 0; i
< fc
->members
->len
; i
++) {
419 struct ctf_named_field_class
*named_fc
=
420 ctf_field_class_struct_borrow_member_by_index(fc
, i
);
422 if (named_fc
->fc
->in_ir
) {
423 has_immediate_member_in_ir
= true;
429 return has_immediate_member_in_ir
;
432 static inline bt_field_class
*scope_ctf_field_class_to_ir(ctf::MetaTranslateCtx
*ctx
)
434 bt_field_class
*ir_fc
= NULL
;
435 struct ctf_field_class
*fc
= NULL
;
437 switch (ctx
->scope
) {
438 case CTF_SCOPE_PACKET_CONTEXT
:
439 fc
= ctx
->sc
->packet_context_fc
;
441 case CTF_SCOPE_EVENT_COMMON_CONTEXT
:
442 fc
= ctx
->sc
->event_common_context_fc
;
444 case CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
:
445 fc
= ctx
->ec
->spec_context_fc
;
447 case CTF_SCOPE_EVENT_PAYLOAD
:
448 fc
= ctx
->ec
->payload_fc
;
454 if (fc
&& ctf_field_class_struct_has_immediate_member_in_ir(ctf_field_class_as_struct(fc
))) {
455 ir_fc
= ctf_field_class_to_ir(ctx
, fc
);
461 static inline void ctf_event_class_to_ir(ctf::MetaTranslateCtx
*ctx
)
464 bt_event_class
*ir_ec
= NULL
;
465 bt_field_class
*ir_fc
;
469 if (ctx
->ec
->is_translated
) {
470 ir_ec
= bt_stream_class_borrow_event_class_by_id(ctx
->ir_sc
, ctx
->ec
->id
);
475 ir_ec
= bt_event_class_create_with_id(ctx
->ir_sc
, ctx
->ec
->id
);
477 bt_event_class_put_ref(ir_ec
);
478 ctx
->scope
= CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
;
479 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
481 ret
= bt_event_class_set_specific_context_field_class(ir_ec
, ir_fc
);
483 bt_field_class_put_ref(ir_fc
);
486 ctx
->scope
= CTF_SCOPE_EVENT_PAYLOAD
;
487 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
489 ret
= bt_event_class_set_payload_field_class(ir_ec
, ir_fc
);
491 bt_field_class_put_ref(ir_fc
);
494 if (ctx
->ec
->name
->len
> 0) {
495 ret
= bt_event_class_set_name(ir_ec
, ctx
->ec
->name
->str
);
499 if (ctx
->ec
->emf_uri
->len
> 0) {
500 ret
= bt_event_class_set_emf_uri(ir_ec
, ctx
->ec
->emf_uri
->str
);
504 if (ctx
->ec
->is_log_level_set
) {
505 bt_event_class_set_log_level(ir_ec
, ctx
->ec
->log_level
);
508 ctx
->ec
->is_translated
= true;
509 ctx
->ec
->ir_ec
= ir_ec
;
515 static inline void ctf_stream_class_to_ir(ctf::MetaTranslateCtx
*ctx
)
518 bt_field_class
*ir_fc
;
522 if (ctx
->sc
->is_translated
) {
523 ctx
->ir_sc
= bt_trace_class_borrow_stream_class_by_id(ctx
->ir_tc
, ctx
->sc
->id
);
524 BT_ASSERT(ctx
->ir_sc
);
528 ctx
->ir_sc
= bt_stream_class_create_with_id(ctx
->ir_tc
, ctx
->sc
->id
);
529 BT_ASSERT(ctx
->ir_sc
);
530 bt_stream_class_put_ref(ctx
->ir_sc
);
532 if (ctx
->sc
->default_clock_class
) {
533 BT_ASSERT(ctx
->sc
->default_clock_class
->ir_cc
);
534 ret
= bt_stream_class_set_default_clock_class(ctx
->ir_sc
,
535 ctx
->sc
->default_clock_class
->ir_cc
);
539 bt_stream_class_set_supports_packets(ctx
->ir_sc
, BT_TRUE
, ctx
->sc
->packets_have_ts_begin
,
540 ctx
->sc
->packets_have_ts_end
);
541 bt_stream_class_set_supports_discarded_events(ctx
->ir_sc
, ctx
->sc
->has_discarded_events
,
542 ctx
->sc
->discarded_events_have_default_cs
);
543 bt_stream_class_set_supports_discarded_packets(ctx
->ir_sc
, ctx
->sc
->has_discarded_packets
,
544 ctx
->sc
->discarded_packets_have_default_cs
);
545 ctx
->scope
= CTF_SCOPE_PACKET_CONTEXT
;
546 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
548 ret
= bt_stream_class_set_packet_context_field_class(ctx
->ir_sc
, ir_fc
);
550 bt_field_class_put_ref(ir_fc
);
553 ctx
->scope
= CTF_SCOPE_EVENT_COMMON_CONTEXT
;
554 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
556 ret
= bt_stream_class_set_event_common_context_field_class(ctx
->ir_sc
, ir_fc
);
558 bt_field_class_put_ref(ir_fc
);
561 bt_stream_class_set_assigns_automatic_event_class_id(ctx
->ir_sc
, BT_FALSE
);
562 bt_stream_class_set_assigns_automatic_stream_id(ctx
->ir_sc
, BT_FALSE
);
564 ctx
->sc
->is_translated
= true;
565 ctx
->sc
->ir_sc
= ctx
->ir_sc
;
571 static inline void ctf_clock_class_to_ir(bt_clock_class
*ir_cc
, struct ctf_clock_class
*cc
)
575 if (strlen(cc
->name
->str
) > 0) {
576 ret
= bt_clock_class_set_name(ir_cc
, cc
->name
->str
);
580 if (strlen(cc
->description
->str
) > 0) {
581 ret
= bt_clock_class_set_description(ir_cc
, cc
->description
->str
);
585 bt_clock_class_set_frequency(ir_cc
, cc
->frequency
);
586 bt_clock_class_set_precision(ir_cc
, cc
->precision
);
587 bt_clock_class_set_offset(ir_cc
, cc
->offset_seconds
, cc
->offset_cycles
);
590 bt_clock_class_set_uuid(ir_cc
, cc
->uuid
);
593 bt_clock_class_set_origin_is_unix_epoch(ir_cc
, cc
->is_absolute
);
596 static inline int ctf_trace_class_to_ir(ctf::MetaTranslateCtx
*ctx
)
602 BT_ASSERT(ctx
->ir_tc
);
604 if (ctx
->tc
->is_translated
) {
608 for (i
= 0; i
< ctx
->tc
->clock_classes
->len
; i
++) {
609 ctf_clock_class
*cc
= (ctf_clock_class
*) ctx
->tc
->clock_classes
->pdata
[i
];
611 cc
->ir_cc
= bt_clock_class_create(ctx
->self_comp
);
612 ctf_clock_class_to_ir(cc
->ir_cc
, cc
);
615 bt_trace_class_set_assigns_automatic_stream_class_id(ctx
->ir_tc
, BT_FALSE
);
616 ctx
->tc
->is_translated
= true;
617 ctx
->tc
->ir_tc
= ctx
->ir_tc
;
623 int ctf_trace_class_translate(bt_self_component
*self_comp
, bt_trace_class
*ir_tc
,
624 struct ctf_trace_class
*tc
)
628 ctf::MetaTranslateCtx ctx
= {};
630 ctx
.self_comp
= self_comp
;
633 ret
= ctf_trace_class_to_ir(&ctx
);
638 for (i
= 0; i
< tc
->stream_classes
->len
; i
++) {
640 ctx
.sc
= (ctf_stream_class
*) tc
->stream_classes
->pdata
[i
];
642 ctf_stream_class_to_ir(&ctx
);
644 for (j
= 0; j
< ctx
.sc
->event_classes
->len
; j
++) {
645 ctx
.ec
= (ctf_event_class
*) ctx
.sc
->event_classes
->pdata
[j
];
647 ctf_event_class_to_ir(&ctx
);