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"
23 #include "ctf-meta-visitors.h"
26 bt_self_component
*self_comp
;
27 bt_trace_class
*ir_tc
;
28 bt_stream_class
*ir_sc
;
29 struct ctf_trace_class
*tc
;
30 struct ctf_stream_class
*sc
;
31 struct ctf_event_class
*ec
;
36 bt_field_class
*ctf_field_class_to_ir(struct ctx
*ctx
,
37 struct ctf_field_class
*fc
);
40 void ctf_field_class_int_set_props(struct ctf_field_class_int
*fc
,
41 bt_field_class
*ir_fc
)
43 bt_field_class_integer_set_field_value_range(ir_fc
,
45 bt_field_class_integer_set_preferred_display_base(ir_fc
,
50 bt_field_class
*ctf_field_class_int_to_ir(struct ctx
*ctx
,
51 struct ctf_field_class_int
*fc
)
53 bt_field_class
*ir_fc
;
56 ir_fc
= bt_field_class_signed_integer_create(ctx
->ir_tc
);
58 ir_fc
= bt_field_class_unsigned_integer_create(ctx
->ir_tc
);
62 ctf_field_class_int_set_props(fc
, ir_fc
);
67 bt_field_class
*ctf_field_class_enum_to_ir(struct ctx
*ctx
,
68 struct ctf_field_class_enum
*fc
)
71 bt_field_class
*ir_fc
;
74 if (fc
->base
.is_signed
) {
75 ir_fc
= bt_field_class_signed_enumeration_create(ctx
->ir_tc
);
77 ir_fc
= bt_field_class_unsigned_enumeration_create(ctx
->ir_tc
);
81 ctf_field_class_int_set_props((void *) fc
, ir_fc
);
83 for (i
= 0; i
< fc
->mappings
->len
; i
++) {
84 struct ctf_field_class_enum_mapping
*mapping
=
85 ctf_field_class_enum_borrow_mapping_by_index(fc
, i
);
87 if (fc
->base
.is_signed
) {
88 ret
= bt_field_class_signed_enumeration_map_range(
89 ir_fc
, mapping
->label
->str
,
90 mapping
->range
.lower
.i
, mapping
->range
.upper
.i
);
92 ret
= bt_field_class_unsigned_enumeration_map_range(
93 ir_fc
, mapping
->label
->str
,
94 mapping
->range
.lower
.u
, mapping
->range
.upper
.u
);
104 bt_field_class
*ctf_field_class_float_to_ir(struct ctx
*ctx
,
105 struct ctf_field_class_float
*fc
)
107 bt_field_class
*ir_fc
;
109 ir_fc
= bt_field_class_real_create(ctx
->ir_tc
);
112 if (fc
->base
.size
== 32) {
113 bt_field_class_real_set_is_single_precision(ir_fc
,
121 bt_field_class
*ctf_field_class_string_to_ir(struct ctx
*ctx
,
122 struct ctf_field_class_string
*fc
)
124 bt_field_class
*ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
131 void translate_struct_field_class_members(struct ctx
*ctx
,
132 struct ctf_field_class_struct
*fc
, bt_field_class
*ir_fc
,
133 bool with_header_prefix
,
134 struct ctf_field_class_struct
*context_fc
)
139 for (i
= 0; i
< fc
->members
->len
; i
++) {
140 struct ctf_named_field_class
*named_fc
=
141 ctf_field_class_struct_borrow_member_by_index(fc
, i
);
142 bt_field_class
*member_ir_fc
;
143 const char *name
= named_fc
->name
->str
;
145 if (!named_fc
->fc
->in_ir
) {
149 member_ir_fc
= ctf_field_class_to_ir(ctx
, named_fc
->fc
);
150 BT_ASSERT(member_ir_fc
);
151 ret
= bt_field_class_structure_append_member(ir_fc
, name
,
154 bt_field_class_put_ref(member_ir_fc
);
159 bt_field_class
*ctf_field_class_struct_to_ir(struct ctx
*ctx
,
160 struct ctf_field_class_struct
*fc
)
162 bt_field_class
*ir_fc
= bt_field_class_structure_create(ctx
->ir_tc
);
165 translate_struct_field_class_members(ctx
, fc
, ir_fc
, false, NULL
);
170 bt_field_class
*borrow_ir_fc_from_field_path(struct ctx
*ctx
,
171 struct ctf_field_path
*field_path
)
173 bt_field_class
*ir_fc
= NULL
;
174 struct ctf_field_class
*fc
= ctf_field_path_borrow_field_class(
175 field_path
, ctx
->tc
, ctx
->sc
, ctx
->ec
);
187 bt_field_class
*ctf_field_class_variant_to_ir(struct ctx
*ctx
,
188 struct ctf_field_class_variant
*fc
)
191 bt_field_class
*ir_fc
= bt_field_class_variant_create(ctx
->ir_tc
);
196 if (fc
->tag_path
.root
!= CTF_SCOPE_PACKET_HEADER
&&
197 fc
->tag_path
.root
!= CTF_SCOPE_EVENT_HEADER
) {
198 ret
= bt_field_class_variant_set_selector_field_class(
199 ir_fc
, borrow_ir_fc_from_field_path(ctx
,
204 for (i
= 0; i
< fc
->options
->len
; i
++) {
205 struct ctf_named_field_class
*named_fc
=
206 ctf_field_class_variant_borrow_option_by_index(fc
, i
);
207 bt_field_class
*option_ir_fc
;
209 BT_ASSERT(named_fc
->fc
->in_ir
);
210 option_ir_fc
= ctf_field_class_to_ir(ctx
, named_fc
->fc
);
211 BT_ASSERT(option_ir_fc
);
212 ret
= bt_field_class_variant_append_option(
213 ir_fc
, named_fc
->name
->str
, option_ir_fc
);
215 bt_field_class_put_ref(option_ir_fc
);
222 bt_field_class
*ctf_field_class_array_to_ir(struct ctx
*ctx
,
223 struct ctf_field_class_array
*fc
)
225 bt_field_class
*ir_fc
;
226 bt_field_class
*elem_ir_fc
;
228 if (fc
->base
.is_text
) {
229 ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
234 elem_ir_fc
= ctf_field_class_to_ir(ctx
, fc
->base
.elem_fc
);
235 BT_ASSERT(elem_ir_fc
);
236 ir_fc
= bt_field_class_static_array_create(ctx
->ir_tc
, elem_ir_fc
,
239 bt_field_class_put_ref(elem_ir_fc
);
246 bt_field_class
*ctf_field_class_sequence_to_ir(struct ctx
*ctx
,
247 struct ctf_field_class_sequence
*fc
)
250 bt_field_class
*ir_fc
;
251 bt_field_class
*elem_ir_fc
;
253 if (fc
->base
.is_text
) {
254 ir_fc
= bt_field_class_string_create(ctx
->ir_tc
);
259 elem_ir_fc
= ctf_field_class_to_ir(ctx
, fc
->base
.elem_fc
);
260 BT_ASSERT(elem_ir_fc
);
261 ir_fc
= bt_field_class_dynamic_array_create(ctx
->ir_tc
, elem_ir_fc
);
263 bt_field_class_put_ref(elem_ir_fc
);
266 if (fc
->length_path
.root
!= CTF_SCOPE_PACKET_HEADER
&&
267 fc
->length_path
.root
!= CTF_SCOPE_EVENT_HEADER
) {
268 ret
= bt_field_class_dynamic_array_set_length_field_class(
269 ir_fc
, borrow_ir_fc_from_field_path(ctx
, &fc
->length_path
));
278 bt_field_class
*ctf_field_class_to_ir(struct ctx
*ctx
,
279 struct ctf_field_class
*fc
)
281 bt_field_class
*ir_fc
= NULL
;
284 BT_ASSERT(fc
->in_ir
);
287 case CTF_FIELD_CLASS_TYPE_INT
:
288 ir_fc
= ctf_field_class_int_to_ir(ctx
, (void *) fc
);
290 case CTF_FIELD_CLASS_TYPE_ENUM
:
291 ir_fc
= ctf_field_class_enum_to_ir(ctx
, (void *) fc
);
293 case CTF_FIELD_CLASS_TYPE_FLOAT
:
294 ir_fc
= ctf_field_class_float_to_ir(ctx
, (void *) fc
);
296 case CTF_FIELD_CLASS_TYPE_STRING
:
297 ir_fc
= ctf_field_class_string_to_ir(ctx
, (void *) fc
);
299 case CTF_FIELD_CLASS_TYPE_STRUCT
:
300 ir_fc
= ctf_field_class_struct_to_ir(ctx
, (void *) fc
);
302 case CTF_FIELD_CLASS_TYPE_ARRAY
:
303 ir_fc
= ctf_field_class_array_to_ir(ctx
, (void *) fc
);
305 case CTF_FIELD_CLASS_TYPE_SEQUENCE
:
306 ir_fc
= ctf_field_class_sequence_to_ir(ctx
, (void *) fc
);
308 case CTF_FIELD_CLASS_TYPE_VARIANT
:
309 ir_fc
= ctf_field_class_variant_to_ir(ctx
, (void *) fc
);
320 bool ctf_field_class_struct_has_immediate_member_in_ir(
321 struct ctf_field_class_struct
*fc
)
324 bool has_immediate_member_in_ir
= false;
327 * If the structure field class has no members at all, then it
328 * was an empty structure in the beginning, so leave it existing
331 if (fc
->members
->len
== 0) {
332 has_immediate_member_in_ir
= true;
336 for (i
= 0; i
< fc
->members
->len
; i
++) {
337 struct ctf_named_field_class
*named_fc
=
338 ctf_field_class_struct_borrow_member_by_index(fc
, i
);
340 if (named_fc
->fc
->in_ir
) {
341 has_immediate_member_in_ir
= true;
347 return has_immediate_member_in_ir
;
351 bt_field_class
*scope_ctf_field_class_to_ir(struct ctx
*ctx
)
353 bt_field_class
*ir_fc
= NULL
;
354 struct ctf_field_class
*fc
= NULL
;
356 switch (ctx
->scope
) {
357 case CTF_SCOPE_PACKET_CONTEXT
:
358 fc
= ctx
->sc
->packet_context_fc
;
360 case CTF_SCOPE_EVENT_COMMON_CONTEXT
:
361 fc
= ctx
->sc
->event_common_context_fc
;
363 case CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
:
364 fc
= ctx
->ec
->spec_context_fc
;
366 case CTF_SCOPE_EVENT_PAYLOAD
:
367 fc
= ctx
->ec
->payload_fc
;
373 if (fc
&& ctf_field_class_struct_has_immediate_member_in_ir(
375 ir_fc
= ctf_field_class_to_ir(ctx
, fc
);
382 void ctf_event_class_to_ir(struct ctx
*ctx
)
385 bt_event_class
*ir_ec
= NULL
;
386 bt_field_class
*ir_fc
;
390 if (ctx
->ec
->is_translated
) {
391 ir_ec
= bt_stream_class_borrow_event_class_by_id(
392 ctx
->ir_sc
, ctx
->ec
->id
);
397 ir_ec
= bt_event_class_create_with_id(ctx
->ir_sc
, ctx
->ec
->id
);
399 bt_event_class_put_ref(ir_ec
);
400 ctx
->scope
= CTF_SCOPE_EVENT_SPECIFIC_CONTEXT
;
401 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
403 ret
= bt_event_class_set_specific_context_field_class(
406 bt_field_class_put_ref(ir_fc
);
409 ctx
->scope
= CTF_SCOPE_EVENT_PAYLOAD
;
410 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
412 ret
= bt_event_class_set_payload_field_class(ir_ec
,
415 bt_field_class_put_ref(ir_fc
);
418 if (ctx
->ec
->name
->len
> 0) {
419 ret
= bt_event_class_set_name(ir_ec
, ctx
->ec
->name
->str
);
423 if (ctx
->ec
->emf_uri
->len
> 0) {
424 ret
= bt_event_class_set_emf_uri(ir_ec
, ctx
->ec
->emf_uri
->str
);
428 if (ctx
->ec
->log_level
!= -1) {
429 bt_event_class_set_log_level(ir_ec
, ctx
->ec
->log_level
);
432 ctx
->ec
->is_translated
= true;
433 ctx
->ec
->ir_ec
= ir_ec
;
441 void ctf_stream_class_to_ir(struct ctx
*ctx
)
444 bt_field_class
*ir_fc
;
448 if (ctx
->sc
->is_translated
) {
449 ctx
->ir_sc
= bt_trace_class_borrow_stream_class_by_id(
450 ctx
->ir_tc
, ctx
->sc
->id
);
451 BT_ASSERT(ctx
->ir_sc
);
455 ctx
->ir_sc
= bt_stream_class_create_with_id(ctx
->ir_tc
, ctx
->sc
->id
);
456 BT_ASSERT(ctx
->ir_sc
);
457 bt_stream_class_put_ref(ctx
->ir_sc
);
459 if (ctx
->sc
->default_clock_class
) {
460 BT_ASSERT(ctx
->sc
->default_clock_class
->ir_cc
);
461 ret
= bt_stream_class_set_default_clock_class(ctx
->ir_sc
,
462 ctx
->sc
->default_clock_class
->ir_cc
);
466 bt_stream_class_set_supports_packets(ctx
->ir_sc
, BT_TRUE
,
467 ctx
->sc
->packets_have_ts_begin
, ctx
->sc
->packets_have_ts_end
);
468 bt_stream_class_set_supports_discarded_events(ctx
->ir_sc
,
469 ctx
->sc
->has_discarded_events
,
470 ctx
->sc
->discarded_events_have_default_cs
);
471 bt_stream_class_set_supports_discarded_packets(ctx
->ir_sc
,
472 ctx
->sc
->has_discarded_packets
,
473 ctx
->sc
->discarded_packets_have_default_cs
);
474 ctx
->scope
= CTF_SCOPE_PACKET_CONTEXT
;
475 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
477 ret
= bt_stream_class_set_packet_context_field_class(
480 bt_field_class_put_ref(ir_fc
);
483 ctx
->scope
= CTF_SCOPE_EVENT_COMMON_CONTEXT
;
484 ir_fc
= scope_ctf_field_class_to_ir(ctx
);
486 ret
= bt_stream_class_set_event_common_context_field_class(
489 bt_field_class_put_ref(ir_fc
);
492 bt_stream_class_set_assigns_automatic_event_class_id(ctx
->ir_sc
,
494 bt_stream_class_set_assigns_automatic_stream_id(ctx
->ir_sc
, BT_FALSE
);
496 ctx
->sc
->is_translated
= true;
497 ctx
->sc
->ir_sc
= ctx
->ir_sc
;
504 void ctf_clock_class_to_ir(bt_clock_class
*ir_cc
, struct ctf_clock_class
*cc
)
508 if (strlen(cc
->name
->str
) > 0) {
509 ret
= bt_clock_class_set_name(ir_cc
, cc
->name
->str
);
513 if (strlen(cc
->description
->str
) > 0) {
514 ret
= bt_clock_class_set_description(ir_cc
, cc
->description
->str
);
518 bt_clock_class_set_frequency(ir_cc
, cc
->frequency
);
519 bt_clock_class_set_precision(ir_cc
, cc
->precision
);
520 bt_clock_class_set_offset(ir_cc
, cc
->offset_seconds
, cc
->offset_cycles
);
523 bt_clock_class_set_uuid(ir_cc
, cc
->uuid
);
526 bt_clock_class_set_origin_is_unix_epoch(ir_cc
, cc
->is_absolute
);
530 int ctf_trace_class_to_ir(struct ctx
*ctx
)
536 BT_ASSERT(ctx
->ir_tc
);
538 if (ctx
->tc
->is_translated
) {
542 for (i
= 0; i
< ctx
->tc
->clock_classes
->len
; i
++) {
543 struct ctf_clock_class
*cc
= ctx
->tc
->clock_classes
->pdata
[i
];
545 cc
->ir_cc
= bt_clock_class_create(ctx
->self_comp
);
546 ctf_clock_class_to_ir(cc
->ir_cc
, cc
);
549 bt_trace_class_set_assigns_automatic_stream_class_id(ctx
->ir_tc
,
551 ctx
->tc
->is_translated
= true;
552 ctx
->tc
->ir_tc
= ctx
->ir_tc
;
559 int ctf_trace_class_translate(bt_self_component
*self_comp
,
560 bt_trace_class
*ir_tc
, struct ctf_trace_class
*tc
)
564 struct ctx ctx
= { 0 };
566 ctx
.self_comp
= self_comp
;
569 ret
= ctf_trace_class_to_ir(&ctx
);
574 for (i
= 0; i
< tc
->stream_classes
->len
; i
++) {
576 ctx
.sc
= tc
->stream_classes
->pdata
[i
];
578 ctf_stream_class_to_ir(&ctx
);
580 for (j
= 0; j
< ctx
.sc
->event_classes
->len
; j
++) {
581 ctx
.ec
= ctx
.sc
->event_classes
->pdata
[j
];
583 ctf_event_class_to_ir(&ctx
);