2 * Copyright 2018 - Philippe Proulx <pproulx@efficios.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
15 #include <babeltrace2/babeltrace.h>
16 #include "common/macros.h"
17 #include "common/assert.h"
24 #include "ctf-meta-visitors.h"
27 bt_self_component
*self_comp
;
28 bt_trace_class
*ir_tc
;
29 bt_stream_class
*ir_sc
;
30 struct ctf_trace_class
*tc
;
31 struct ctf_stream_class
*sc
;
32 struct ctf_event_class
*ec
;
37 bt_field_class
*ctf_field_class_to_ir(struct ctx
*ctx
,
38 struct ctf_field_class
*fc
);
41 void ctf_field_class_int_set_props(struct ctf_field_class_int
*fc
,
42 bt_field_class
*ir_fc
)
44 bt_field_class_integer_set_field_value_range(ir_fc
,
46 bt_field_class_integer_set_preferred_display_base(ir_fc
,
51 bt_field_class
*ctf_field_class_int_to_ir(struct ctx
*ctx
,
52 struct ctf_field_class_int
*fc
)
54 bt_field_class
*ir_fc
;
57 ir_fc
= bt_field_class_integer_signed_create(ctx
->ir_tc
);
59 ir_fc
= bt_field_class_integer_unsigned_create(ctx
->ir_tc
);
63 ctf_field_class_int_set_props(fc
, ir_fc
);
68 bt_field_class
*ctf_field_class_enum_to_ir(struct ctx
*ctx
,
69 struct ctf_field_class_enum
*fc
)
72 bt_field_class
*ir_fc
;
75 if (fc
->base
.is_signed
) {
76 ir_fc
= bt_field_class_enumeration_signed_create(ctx
->ir_tc
);
78 ir_fc
= bt_field_class_enumeration_unsigned_create(ctx
->ir_tc
);
82 ctf_field_class_int_set_props((void *) fc
, ir_fc
);
84 for (i
= 0; i
< fc
->mappings
->len
; i
++) {
85 struct ctf_field_class_enum_mapping
*mapping
=
86 ctf_field_class_enum_borrow_mapping_by_index(fc
, i
);
90 if (fc
->base
.is_signed
) {
91 range_set
= bt_integer_range_set_signed_create();
93 range_set
= bt_integer_range_set_unsigned_create();
98 for (range_i
= 0; range_i
< mapping
->ranges
->len
; range_i
++) {
99 struct ctf_range
*range
=
100 ctf_field_class_enum_mapping_borrow_range_by_index(
103 if (fc
->base
.is_signed
) {
104 ret
= bt_integer_range_set_signed_add_range(
105 range_set
, range
->lower
.i
,
108 ret
= bt_integer_range_set_unsigned_add_range(
109 range_set
, range
->lower
.u
,
116 if (fc
->base
.is_signed
) {
117 ret
= bt_field_class_enumeration_signed_add_mapping(
118 ir_fc
, mapping
->label
->str
, range_set
);
119 BT_INTEGER_RANGE_SET_SIGNED_PUT_REF_AND_RESET(range_set
);
121 ret
= bt_field_class_enumeration_unsigned_add_mapping(
122 ir_fc
, mapping
->label
->str
, range_set
);
123 BT_INTEGER_RANGE_SET_UNSIGNED_PUT_REF_AND_RESET(range_set
);
133 bt_field_class
*ctf_field_class_float_to_ir(struct ctx
*ctx
,
134 struct ctf_field_class_float
*fc
)
136 bt_field_class
*ir_fc
;
138 if (fc
->base
.size
== 32) {
139 ir_fc
= bt_field_class_real_single_precision_create(ctx
->ir_tc
);
141 ir_fc
= bt_field_class_real_double_precision_create(ctx
->ir_tc
);
149 bt_field_class
*ctf_field_class_string_to_ir(struct ctx
*ctx
,
150 struct ctf_field_class_string
*fc
)
152 bt_field_class
*ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
159 void translate_struct_field_class_members(struct ctx
*ctx
,
160 struct ctf_field_class_struct
*fc
, bt_field_class
*ir_fc
,
161 bool with_header_prefix
,
162 struct ctf_field_class_struct
*context_fc
)
167 for (i
= 0; i
< fc
->members
->len
; i
++) {
168 struct ctf_named_field_class
*named_fc
=
169 ctf_field_class_struct_borrow_member_by_index(fc
, i
);
170 bt_field_class
*member_ir_fc
;
171 const char *name
= named_fc
->name
->str
;
173 if (!named_fc
->fc
->in_ir
) {
177 member_ir_fc
= ctf_field_class_to_ir(ctx
, named_fc
->fc
);
178 BT_ASSERT(member_ir_fc
);
179 ret
= bt_field_class_structure_append_member(ir_fc
, name
,
182 bt_field_class_put_ref(member_ir_fc
);
187 bt_field_class
*ctf_field_class_struct_to_ir(struct ctx
*ctx
,
188 struct ctf_field_class_struct
*fc
)
190 bt_field_class
*ir_fc
= bt_field_class_structure_create(ctx
->ir_tc
);
193 translate_struct_field_class_members(ctx
, fc
, ir_fc
, false, NULL
);
198 bt_field_class
*borrow_ir_fc_from_field_path(struct ctx
*ctx
,
199 struct ctf_field_path
*field_path
)
201 bt_field_class
*ir_fc
= NULL
;
202 struct ctf_field_class
*fc
= ctf_field_path_borrow_field_class(
203 field_path
, ctx
->tc
, ctx
->sc
, ctx
->ec
);
215 const void *find_ir_enum_field_class_mapping_by_label(const bt_field_class
*fc
,
216 const char *label
, bool is_signed
)
218 const void *mapping
= NULL
;
221 for (i
= 0; i
< bt_field_class_enumeration_get_mapping_count(fc
); i
++) {
222 const bt_field_class_enumeration_mapping
*this_mapping
;
223 const void *spec_this_mapping
;
227 bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
230 bt_field_class_enumeration_signed_mapping_as_mapping_const(
234 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
237 bt_field_class_enumeration_unsigned_mapping_as_mapping_const(
241 BT_ASSERT(this_mapping
);
242 BT_ASSERT(spec_this_mapping
);
244 if (strcmp(bt_field_class_enumeration_mapping_get_label(
245 this_mapping
), label
) == 0) {
246 mapping
= spec_this_mapping
;
256 bt_field_class
*ctf_field_class_variant_to_ir(struct ctx
*ctx
,
257 struct ctf_field_class_variant
*fc
)
260 bt_field_class
*ir_fc
;
262 bt_field_class
*ir_tag_fc
= NULL
;
264 if (fc
->tag_path
.root
!= CTF_SCOPE_PACKET_HEADER
&&
265 fc
->tag_path
.root
!= CTF_SCOPE_EVENT_HEADER
) {
266 ir_tag_fc
= borrow_ir_fc_from_field_path(ctx
, &fc
->tag_path
);
267 BT_ASSERT(ir_tag_fc
);
270 ir_fc
= bt_field_class_variant_create(ctx
->ir_tc
, ir_tag_fc
);
273 for (i
= 0; i
< fc
->options
->len
; i
++) {
274 struct ctf_named_field_class
*named_fc
=
275 ctf_field_class_variant_borrow_option_by_index(fc
, i
);
276 bt_field_class
*option_ir_fc
;
278 BT_ASSERT(named_fc
->fc
->in_ir
);
279 option_ir_fc
= ctf_field_class_to_ir(ctx
, named_fc
->fc
);
280 BT_ASSERT(option_ir_fc
);
284 * At this point the trace IR selector
285 * (enumeration) field class already exists if
286 * the variant is tagged (`ir_tag_fc`). This one
287 * already contains range sets for its mappings,
288 * so we just reuse the same, finding them by
289 * matching a variant field class's option's
290 * _original_ name (with a leading underscore,
291 * possibly) with a selector field class's
294 if (fc
->tag_fc
->base
.is_signed
) {
295 const bt_field_class_enumeration_signed_mapping
*mapping
=
296 find_ir_enum_field_class_mapping_by_label(
298 named_fc
->orig_name
->str
, true);
299 const bt_integer_range_set_signed
*range_set
;
303 bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
305 BT_ASSERT(range_set
);
306 ret
= bt_field_class_variant_with_selector_field_integer_signed_append_option(
307 ir_fc
, named_fc
->name
->str
,
308 option_ir_fc
, range_set
);
310 const bt_field_class_enumeration_unsigned_mapping
*mapping
=
311 find_ir_enum_field_class_mapping_by_label(
313 named_fc
->orig_name
->str
,
315 const bt_integer_range_set_unsigned
*range_set
;
319 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
321 BT_ASSERT(range_set
);
322 ret
= bt_field_class_variant_with_selector_field_integer_unsigned_append_option(
323 ir_fc
, named_fc
->name
->str
,
324 option_ir_fc
, range_set
);
327 ret
= bt_field_class_variant_without_selector_append_option(
328 ir_fc
, named_fc
->name
->str
, option_ir_fc
);
332 bt_field_class_put_ref(option_ir_fc
);
339 bt_field_class
*ctf_field_class_array_to_ir(struct ctx
*ctx
,
340 struct ctf_field_class_array
*fc
)
342 bt_field_class
*ir_fc
;
343 bt_field_class
*elem_ir_fc
;
345 if (fc
->base
.is_text
) {
346 ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
351 elem_ir_fc
= ctf_field_class_to_ir(ctx
, fc
->base
.elem_fc
);
352 BT_ASSERT(elem_ir_fc
);
353 ir_fc
= bt_field_class_array_static_create(ctx
->ir_tc
, elem_ir_fc
,
356 bt_field_class_put_ref(elem_ir_fc
);
363 bt_field_class
*ctf_field_class_sequence_to_ir(struct ctx
*ctx
,
364 struct ctf_field_class_sequence
*fc
)
366 bt_field_class
*ir_fc
;
367 bt_field_class
*elem_ir_fc
;
368 bt_field_class
*length_fc
= NULL
;
370 if (fc
->base
.is_text
) {
371 ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
376 elem_ir_fc
= ctf_field_class_to_ir(ctx
, fc
->base
.elem_fc
);
377 BT_ASSERT(elem_ir_fc
);
379 if (fc
->length_path
.root
!= CTF_SCOPE_PACKET_HEADER
&&
380 fc
->length_path
.root
!= CTF_SCOPE_EVENT_HEADER
) {
381 length_fc
= borrow_ir_fc_from_field_path(ctx
, &fc
->length_path
);
382 BT_ASSERT(length_fc
);
385 ir_fc
= bt_field_class_array_dynamic_create(ctx
->ir_tc
, elem_ir_fc
,
388 bt_field_class_put_ref(elem_ir_fc
);
396 bt_field_class
*ctf_field_class_to_ir(struct ctx
*ctx
,
397 struct ctf_field_class
*fc
)
399 bt_field_class
*ir_fc
= NULL
;
402 BT_ASSERT(fc
->in_ir
);
405 case CTF_FIELD_CLASS_TYPE_INT
:
406 ir_fc
= ctf_field_class_int_to_ir(ctx
, (void *) fc
);
408 case CTF_FIELD_CLASS_TYPE_ENUM
:
409 ir_fc
= ctf_field_class_enum_to_ir(ctx
, (void *) fc
);
411 case CTF_FIELD_CLASS_TYPE_FLOAT
:
412 ir_fc
= ctf_field_class_float_to_ir(ctx
, (void *) fc
);
414 case CTF_FIELD_CLASS_TYPE_STRING
:
415 ir_fc
= ctf_field_class_string_to_ir(ctx
, (void *) fc
);
417 case CTF_FIELD_CLASS_TYPE_STRUCT
:
418 ir_fc
= ctf_field_class_struct_to_ir(ctx
, (void *) fc
);
420 case CTF_FIELD_CLASS_TYPE_ARRAY
:
421 ir_fc
= ctf_field_class_array_to_ir(ctx
, (void *) fc
);
423 case CTF_FIELD_CLASS_TYPE_SEQUENCE
:
424 ir_fc
= ctf_field_class_sequence_to_ir(ctx
, (void *) fc
);
426 case CTF_FIELD_CLASS_TYPE_VARIANT
:
427 ir_fc
= ctf_field_class_variant_to_ir(ctx
, (void *) fc
);
438 bool ctf_field_class_struct_has_immediate_member_in_ir(
439 struct ctf_field_class_struct
*fc
)
442 bool has_immediate_member_in_ir
= false;
445 * If the structure field class has no members at all, then it
446 * was an empty structure in the beginning, so leave it existing
449 if (fc
->members
->len
== 0) {
450 has_immediate_member_in_ir
= true;
454 for (i
= 0; i
< fc
->members
->len
; i
++) {
455 struct ctf_named_field_class
*named_fc
=
456 ctf_field_class_struct_borrow_member_by_index(fc
, i
);
458 if (named_fc
->fc
->in_ir
) {
459 has_immediate_member_in_ir
= true;
465 return has_immediate_member_in_ir
;
469 bt_field_class
*scope_ctf_field_class_to_ir(struct ctx
*ctx
)
471 bt_field_class
*ir_fc
= NULL
;
472 struct ctf_field_class
*fc
= NULL
;
474 switch (ctx
->scope
) {
475 case CTF_SCOPE_PACKET_CONTEXT
:
476 fc
= ctx
->sc
->packet_context_fc
;
478 case CTF_SCOPE_EVENT_COMMON_CONTEXT
:
479 fc
= ctx
->sc
->event_common_context_fc
;
481 case CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
:
482 fc
= ctx
->ec
->spec_context_fc
;
484 case CTF_SCOPE_EVENT_PAYLOAD
:
485 fc
= ctx
->ec
->payload_fc
;
491 if (fc
&& ctf_field_class_struct_has_immediate_member_in_ir(
493 ir_fc
= ctf_field_class_to_ir(ctx
, fc
);
500 void ctf_event_class_to_ir(struct ctx
*ctx
)
503 bt_event_class
*ir_ec
= NULL
;
504 bt_field_class
*ir_fc
;
508 if (ctx
->ec
->is_translated
) {
509 ir_ec
= bt_stream_class_borrow_event_class_by_id(
510 ctx
->ir_sc
, ctx
->ec
->id
);
515 ir_ec
= bt_event_class_create_with_id(ctx
->ir_sc
, ctx
->ec
->id
);
517 bt_event_class_put_ref(ir_ec
);
518 ctx
->scope
= CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
;
519 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
521 ret
= bt_event_class_set_specific_context_field_class(
524 bt_field_class_put_ref(ir_fc
);
527 ctx
->scope
= CTF_SCOPE_EVENT_PAYLOAD
;
528 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
530 ret
= bt_event_class_set_payload_field_class(ir_ec
,
533 bt_field_class_put_ref(ir_fc
);
536 if (ctx
->ec
->name
->len
> 0) {
537 ret
= bt_event_class_set_name(ir_ec
, ctx
->ec
->name
->str
);
541 if (ctx
->ec
->emf_uri
->len
> 0) {
542 ret
= bt_event_class_set_emf_uri(ir_ec
, ctx
->ec
->emf_uri
->str
);
546 if (ctx
->ec
->is_log_level_set
) {
547 bt_event_class_set_log_level(ir_ec
, ctx
->ec
->log_level
);
550 ctx
->ec
->is_translated
= true;
551 ctx
->ec
->ir_ec
= ir_ec
;
559 void ctf_stream_class_to_ir(struct ctx
*ctx
)
562 bt_field_class
*ir_fc
;
566 if (ctx
->sc
->is_translated
) {
567 ctx
->ir_sc
= bt_trace_class_borrow_stream_class_by_id(
568 ctx
->ir_tc
, ctx
->sc
->id
);
569 BT_ASSERT(ctx
->ir_sc
);
573 ctx
->ir_sc
= bt_stream_class_create_with_id(ctx
->ir_tc
, ctx
->sc
->id
);
574 BT_ASSERT(ctx
->ir_sc
);
575 bt_stream_class_put_ref(ctx
->ir_sc
);
577 if (ctx
->sc
->default_clock_class
) {
578 BT_ASSERT(ctx
->sc
->default_clock_class
->ir_cc
);
579 ret
= bt_stream_class_set_default_clock_class(ctx
->ir_sc
,
580 ctx
->sc
->default_clock_class
->ir_cc
);
584 bt_stream_class_set_supports_packets(ctx
->ir_sc
, BT_TRUE
,
585 ctx
->sc
->packets_have_ts_begin
, ctx
->sc
->packets_have_ts_end
);
586 bt_stream_class_set_supports_discarded_events(ctx
->ir_sc
,
587 ctx
->sc
->has_discarded_events
,
588 ctx
->sc
->discarded_events_have_default_cs
);
589 bt_stream_class_set_supports_discarded_packets(ctx
->ir_sc
,
590 ctx
->sc
->has_discarded_packets
,
591 ctx
->sc
->discarded_packets_have_default_cs
);
592 ctx
->scope
= CTF_SCOPE_PACKET_CONTEXT
;
593 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
595 ret
= bt_stream_class_set_packet_context_field_class(
598 bt_field_class_put_ref(ir_fc
);
601 ctx
->scope
= CTF_SCOPE_EVENT_COMMON_CONTEXT
;
602 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
604 ret
= bt_stream_class_set_event_common_context_field_class(
607 bt_field_class_put_ref(ir_fc
);
610 bt_stream_class_set_assigns_automatic_event_class_id(ctx
->ir_sc
,
612 bt_stream_class_set_assigns_automatic_stream_id(ctx
->ir_sc
, BT_FALSE
);
614 ctx
->sc
->is_translated
= true;
615 ctx
->sc
->ir_sc
= ctx
->ir_sc
;
622 void ctf_clock_class_to_ir(bt_clock_class
*ir_cc
, struct ctf_clock_class
*cc
)
626 if (strlen(cc
->name
->str
) > 0) {
627 ret
= bt_clock_class_set_name(ir_cc
, cc
->name
->str
);
631 if (strlen(cc
->description
->str
) > 0) {
632 ret
= bt_clock_class_set_description(ir_cc
, cc
->description
->str
);
636 bt_clock_class_set_frequency(ir_cc
, cc
->frequency
);
637 bt_clock_class_set_precision(ir_cc
, cc
->precision
);
638 bt_clock_class_set_offset(ir_cc
, cc
->offset_seconds
, cc
->offset_cycles
);
641 bt_clock_class_set_uuid(ir_cc
, cc
->uuid
);
644 bt_clock_class_set_origin_is_unix_epoch(ir_cc
, cc
->is_absolute
);
648 int ctf_trace_class_to_ir(struct ctx
*ctx
)
654 BT_ASSERT(ctx
->ir_tc
);
656 if (ctx
->tc
->is_translated
) {
660 for (i
= 0; i
< ctx
->tc
->clock_classes
->len
; i
++) {
661 struct ctf_clock_class
*cc
= ctx
->tc
->clock_classes
->pdata
[i
];
663 cc
->ir_cc
= bt_clock_class_create(ctx
->self_comp
);
664 ctf_clock_class_to_ir(cc
->ir_cc
, cc
);
667 bt_trace_class_set_assigns_automatic_stream_class_id(ctx
->ir_tc
,
669 ctx
->tc
->is_translated
= true;
670 ctx
->tc
->ir_tc
= ctx
->ir_tc
;
677 int ctf_trace_class_translate(bt_self_component
*self_comp
,
678 bt_trace_class
*ir_tc
, struct ctf_trace_class
*tc
)
682 struct ctx ctx
= { 0 };
684 ctx
.self_comp
= self_comp
;
687 ret
= ctf_trace_class_to_ir(&ctx
);
692 for (i
= 0; i
< tc
->stream_classes
->len
; i
++) {
694 ctx
.sc
= tc
->stream_classes
->pdata
[i
];
696 ctf_stream_class_to_ir(&ctx
);
698 for (j
= 0; j
< ctx
.sc
->event_classes
->len
; j
++) {
699 ctx
.ec
= ctx
.sc
->event_classes
->pdata
[j
];
701 ctf_event_class_to_ir(&ctx
);