Sort includes in C++ files
[babeltrace.git] / src / plugins / ctf / common / metadata / ctf-meta-update-in-ir.cpp
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
5 */
6
7 #include <glib.h>
8 #include <inttypes.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 #include <string.h>
12
13 #include <babeltrace2/babeltrace.h>
14
15 #include "common/assert.h"
16 #include "common/macros.h"
17 #include "compat/glib.h"
18
19 #include "ctf-meta-visitors.hpp"
20
21 static void force_update_field_class_in_ir(struct ctf_field_class *fc, bool in_ir)
22 {
23 uint64_t i;
24
25 if (!fc) {
26 goto end;
27 }
28
29 fc->in_ir = in_ir;
30
31 switch (fc->type) {
32 case CTF_FIELD_CLASS_TYPE_STRUCT:
33 {
34 struct ctf_field_class_struct *struct_fc = ctf_field_class_as_struct(fc);
35
36 for (i = 0; i < struct_fc->members->len; i++) {
37 struct ctf_named_field_class *named_fc =
38 ctf_field_class_struct_borrow_member_by_index(struct_fc, i);
39
40 force_update_field_class_in_ir(named_fc->fc, in_ir);
41 }
42
43 break;
44 }
45 case CTF_FIELD_CLASS_TYPE_VARIANT:
46 {
47 struct ctf_named_field_class *named_fc;
48 struct ctf_field_class_variant *var_fc = ctf_field_class_as_variant(fc);
49
50 for (i = 0; i < var_fc->options->len; i++) {
51 named_fc = ctf_field_class_variant_borrow_option_by_index(var_fc, i);
52
53 force_update_field_class_in_ir(named_fc->fc, in_ir);
54 }
55
56 break;
57 }
58 case CTF_FIELD_CLASS_TYPE_ARRAY:
59 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
60 {
61 struct ctf_field_class_array_base *array_fc = ctf_field_class_as_array_base(fc);
62
63 force_update_field_class_in_ir(array_fc->elem_fc, in_ir);
64 break;
65 }
66 default:
67 break;
68 }
69
70 end:
71 return;
72 }
73
74 static void update_field_class_in_ir(struct ctf_field_class *fc, GHashTable *ft_dependents)
75 {
76 int64_t i;
77
78 if (!fc) {
79 goto end;
80 }
81
82 switch (fc->type) {
83 case CTF_FIELD_CLASS_TYPE_INT:
84 case CTF_FIELD_CLASS_TYPE_ENUM:
85 {
86 struct ctf_field_class_int *int_fc = ctf_field_class_as_int(fc);
87
88 /*
89 * Conditions to be in trace IR; one of:
90 *
91 * 1. Does NOT have a mapped clock class AND does not
92 * have a special meaning.
93 * 2. Another field class depends on it.
94 */
95 if ((!int_fc->mapped_clock_class && int_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE) ||
96 bt_g_hash_table_contains(ft_dependents, fc)) {
97 fc->in_ir = true;
98 }
99
100 break;
101 }
102 case CTF_FIELD_CLASS_TYPE_STRUCT:
103 {
104 struct ctf_field_class_struct *struct_fc = ctf_field_class_as_struct(fc);
105
106 /*
107 * Make it part of IR if it's empty because it was
108 * originally empty.
109 */
110 if (struct_fc->members->len == 0) {
111 fc->in_ir = true;
112 }
113
114 /* Reverse order */
115 for (i = (int64_t) struct_fc->members->len - 1; i >= 0; i--) {
116 struct ctf_named_field_class *named_fc =
117 ctf_field_class_struct_borrow_member_by_index(struct_fc, i);
118
119 update_field_class_in_ir(named_fc->fc, ft_dependents);
120
121 if (named_fc->fc->in_ir) {
122 /* At least one member is part of IR */
123 fc->in_ir = true;
124 }
125 }
126
127 break;
128 }
129 case CTF_FIELD_CLASS_TYPE_VARIANT:
130 {
131 struct ctf_named_field_class *named_fc;
132 struct ctf_field_class_variant *var_fc = ctf_field_class_as_variant(fc);
133
134 /*
135 * Reverse order, although it is not important for this
136 * loop because a field class within a variant field
137 * type's option cannot depend on a field class in
138 * another option of the same variant field class.
139 */
140 for (i = (int64_t) var_fc->options->len - 1; i >= 0; i--) {
141 named_fc = ctf_field_class_variant_borrow_option_by_index(var_fc, i);
142
143 update_field_class_in_ir(named_fc->fc, ft_dependents);
144
145 if (named_fc->fc->in_ir) {
146 /* At least one option is part of IR */
147 fc->in_ir = true;
148 }
149 }
150
151 if (fc->in_ir) {
152 /*
153 * At least one option will make it to IR. In
154 * this case, make all options part of IR
155 * because the variant's tag could still select
156 * (dynamically) a removed option. This can mean
157 * having an empty structure as an option, for
158 * example, but at least all the options are
159 * selectable.
160 */
161 for (i = 0; i < var_fc->options->len; i++) {
162 ctf_field_class_variant_borrow_option_by_index(var_fc, i)->fc->in_ir = true;
163 }
164
165 /*
166 * This variant field class is part of IR and
167 * depends on a tag field class (which must also
168 * be part of IR).
169 */
170 g_hash_table_insert(ft_dependents, var_fc->tag_fc, var_fc->tag_fc);
171 }
172
173 break;
174 }
175 case CTF_FIELD_CLASS_TYPE_ARRAY:
176 case CTF_FIELD_CLASS_TYPE_SEQUENCE:
177 {
178 struct ctf_field_class_array_base *array_fc = ctf_field_class_as_array_base(fc);
179
180 update_field_class_in_ir(array_fc->elem_fc, ft_dependents);
181 fc->in_ir = array_fc->elem_fc->in_ir;
182
183 if (fc->type == CTF_FIELD_CLASS_TYPE_ARRAY) {
184 struct ctf_field_class_array *arr_fc = ctf_field_class_as_array(fc);
185
186 assert(arr_fc->meaning == CTF_FIELD_CLASS_MEANING_NONE ||
187 arr_fc->meaning == CTF_FIELD_CLASS_MEANING_UUID);
188
189 /*
190 * UUID field class: nothing depends on this, so
191 * it's not part of IR.
192 */
193 if (arr_fc->meaning == CTF_FIELD_CLASS_MEANING_UUID) {
194 fc->in_ir = false;
195 array_fc->elem_fc->in_ir = false;
196 }
197 } else if (fc->type == CTF_FIELD_CLASS_TYPE_SEQUENCE) {
198 if (fc->in_ir) {
199 struct ctf_field_class_sequence *seq_fc = ctf_field_class_as_sequence(fc);
200
201 /*
202 * This sequence field class is part of
203 * IR and depends on a length field class
204 * (which must also be part of IR).
205 */
206 g_hash_table_insert(ft_dependents, seq_fc->length_fc, seq_fc->length_fc);
207 }
208 }
209
210 break;
211 }
212 default:
213 fc->in_ir = true;
214 break;
215 }
216
217 end:
218 return;
219 }
220
221 /*
222 * Scopes and field classes are processed in reverse order because we need
223 * to know if a given integer field class has dependents (sequence or
224 * variant field classes) when we reach it. Dependents can only be located
225 * after the length/tag field class in the metadata tree.
226 */
227 int ctf_trace_class_update_in_ir(struct ctf_trace_class *ctf_tc)
228 {
229 int ret = 0;
230 uint64_t i;
231
232 GHashTable *ft_dependents = g_hash_table_new(g_direct_hash, g_direct_equal);
233
234 BT_ASSERT(ft_dependents);
235
236 for (i = 0; i < ctf_tc->stream_classes->len; i++) {
237 ctf_stream_class *sc = (ctf_stream_class *) ctf_tc->stream_classes->pdata[i];
238 uint64_t j;
239
240 for (j = 0; j < sc->event_classes->len; j++) {
241 ctf_event_class *ec = (ctf_event_class *) sc->event_classes->pdata[j];
242
243 if (ec->is_translated) {
244 continue;
245 }
246
247 update_field_class_in_ir(ec->payload_fc, ft_dependents);
248 update_field_class_in_ir(ec->spec_context_fc, ft_dependents);
249 }
250
251 if (!sc->is_translated) {
252 update_field_class_in_ir(sc->event_common_context_fc, ft_dependents);
253 force_update_field_class_in_ir(sc->event_header_fc, false);
254 update_field_class_in_ir(sc->packet_context_fc, ft_dependents);
255 }
256 }
257
258 if (!ctf_tc->is_translated) {
259 force_update_field_class_in_ir(ctf_tc->packet_header_fc, false);
260 }
261
262 g_hash_table_destroy(ft_dependents);
263 return ret;
264 }
This page took 0.037497 seconds and 4 git commands to generate.