Commit | Line | Data |
---|---|---|
e5aa0be3 PP |
1 | # The MIT License (MIT) |
2 | # | |
4a90140d | 3 | # Copyright (c) 2014-2020 Philippe Proulx <pproulx@efficios.com> |
e5aa0be3 | 4 | # |
1378f213 PP |
5 | # Permission is hereby granted, free of charge, to any person obtaining |
6 | # a copy of this software and associated documentation files (the | |
7 | # "Software"), to deal in the Software without restriction, including | |
8 | # without limitation the rights to use, copy, modify, merge, publish, | |
9 | # distribute, sublicense, and/or sell copies of the Software, and to | |
10 | # permit persons to whom the Software is furnished to do so, subject to | |
11 | # the following conditions: | |
e5aa0be3 | 12 | # |
1378f213 PP |
13 | # The above copyright notice and this permission notice shall be |
14 | # included in all copies or substantial portions of the Software. | |
e5aa0be3 | 15 | # |
1378f213 PP |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
18 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
19 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
20 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
21 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
22 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
e5aa0be3 | 23 | |
4810b707 PP |
24 | import barectf.tsdl182gen as barectf_tsdl182gen |
25 | import barectf.templates as barectf_templates | |
26 | import barectf.codegen as barectf_codegen | |
27 | import barectf.config as barectf_config | |
28 | import barectf.version as barectf_version | |
acfb8213 | 29 | import itertools |
e5aa0be3 | 30 | import datetime |
acfb8213 | 31 | import copy |
4810b707 PP |
32 | |
33 | ||
34 | class _GeneratedFile: | |
35 | def __init__(self, name, contents): | |
36 | self._name = name | |
37 | self._contents = contents | |
38 | ||
39 | @property | |
40 | def name(self): | |
41 | return self._name | |
42 | ||
43 | @property | |
44 | def contents(self): | |
45 | return self._contents | |
46 | ||
47 | ||
48 | class CodeGenerator: | |
49 | def __init__(self, configuration): | |
50 | self._config = configuration | |
51 | self._file_name_prefix = configuration.options.code_generation_options.file_name_prefix | |
52 | self._ccode_gen = _CCodeGenerator(configuration) | |
53 | self._c_headers = None | |
54 | self._c_sources = None | |
55 | self._metadata_stream = None | |
56 | ||
57 | @property | |
58 | def _barectf_header_name(self): | |
59 | return f'{self._file_name_prefix}.h' | |
60 | ||
61 | def generate_c_headers(self): | |
62 | if self._c_headers is None: | |
63 | bitfield_header_name = f'{self._file_name_prefix}-bitfield.h' | |
64 | self._c_headers = [ | |
65 | _GeneratedFile(self._barectf_header_name, | |
66 | self._ccode_gen.generate_header(bitfield_header_name)), | |
67 | _GeneratedFile(bitfield_header_name, | |
68 | self._ccode_gen.generate_bitfield_header()), | |
69 | ] | |
70 | ||
71 | return self._c_headers | |
72 | ||
73 | def generate_c_sources(self): | |
74 | if self._c_sources is None: | |
75 | self._c_sources = [ | |
76 | _GeneratedFile(f'{self._file_name_prefix}.c', | |
77 | self._ccode_gen.generate_c_src(self._barectf_header_name)) | |
78 | ] | |
79 | ||
80 | return self._c_sources | |
81 | ||
82 | def generate_metadata_stream(self): | |
83 | if self._metadata_stream is None: | |
84 | self._metadata_stream = _GeneratedFile('metadata', | |
85 | barectf_tsdl182gen._from_config(self._config)) | |
86 | ||
87 | return self._metadata_stream | |
e5aa0be3 PP |
88 | |
89 | ||
70e191bd PP |
90 | def _align(v, align): |
91 | return (v + (align - 1)) & -align | |
92 | ||
93 | ||
acfb8213 | 94 | class _SerializationAction: |
4810b707 | 95 | def __init__(self, offset_in_byte, ft, names): |
acfb8213 PP |
96 | assert(offset_in_byte >= 0 and offset_in_byte < 8) |
97 | self._offset_in_byte = offset_in_byte | |
4810b707 | 98 | self._ft = ft |
acfb8213 | 99 | self._names = copy.deepcopy(names) |
e5aa0be3 PP |
100 | |
101 | @property | |
acfb8213 PP |
102 | def offset_in_byte(self): |
103 | return self._offset_in_byte | |
e5aa0be3 | 104 | |
acfb8213 | 105 | @property |
4810b707 PP |
106 | def ft(self): |
107 | return self._ft | |
acfb8213 PP |
108 | |
109 | @property | |
110 | def names(self): | |
111 | return self._names | |
e5aa0be3 | 112 | |
e5aa0be3 | 113 | |
acfb8213 | 114 | class _AlignSerializationAction(_SerializationAction): |
4810b707 PP |
115 | def __init__(self, offset_in_byte, ft, names, value): |
116 | super().__init__(offset_in_byte, ft, names) | |
acfb8213 | 117 | self._value = value |
e5aa0be3 | 118 | |
acfb8213 PP |
119 | @property |
120 | def value(self): | |
121 | return self._value | |
e5aa0be3 | 122 | |
e5aa0be3 | 123 | |
acfb8213 | 124 | class _SerializeSerializationAction(_SerializationAction): |
4810b707 | 125 | pass |
70e191bd | 126 | |
e5aa0be3 | 127 | |
acfb8213 PP |
128 | class _SerializationActions: |
129 | def __init__(self): | |
130 | self.reset() | |
e5aa0be3 | 131 | |
70e191bd | 132 | def reset(self): |
acfb8213 PP |
133 | self._last_alignment = None |
134 | self._last_bit_array_size = None | |
135 | self._actions = [] | |
136 | self._names = [] | |
137 | self._offset_in_byte = 0 | |
138 | ||
4810b707 PP |
139 | def append_root_scope_ft(self, ft, name): |
140 | if ft is None: | |
acfb8213 | 141 | return |
e5aa0be3 | 142 | |
4810b707 | 143 | assert(type(ft) is barectf_config.StructureFieldType) |
acfb8213 | 144 | self._names = [name] |
4810b707 | 145 | self._append_ft(ft) |
e5aa0be3 | 146 | |
acfb8213 PP |
147 | @property |
148 | def actions(self): | |
149 | return self._actions | |
150 | ||
151 | def align(self, alignment): | |
152 | do_align = self._must_align(alignment) | |
153 | self._last_alignment = alignment | |
154 | self._last_bit_array_size = alignment | |
155 | self._try_append_align_action(alignment, do_align) | |
156 | ||
157 | def _must_align(self, align_req): | |
158 | return self._last_alignment != align_req or self._last_bit_array_size % align_req != 0 | |
159 | ||
4810b707 PP |
160 | def _append_ft(self, ft): |
161 | if isinstance(ft, (barectf_config.StringFieldType, barectf_config._ArrayFieldType)): | |
162 | assert(type(ft) is barectf_config.StringFieldType or self._names[-1] == 'uuid') | |
acfb8213 PP |
163 | do_align = self._must_align(8) |
164 | self._last_alignment = 8 | |
165 | self._last_bit_array_size = 8 | |
4810b707 PP |
166 | self._try_append_align_action(8, do_align, ft) |
167 | self._append_serialize_action(ft) | |
168 | else: | |
169 | do_align = self._must_align(ft.alignment) | |
170 | self._last_alignment = ft.alignment | |
171 | ||
172 | if type(ft) is barectf_config.StructureFieldType: | |
173 | self._last_bit_array_size = ft.alignment | |
acfb8213 | 174 | else: |
4810b707 | 175 | self._last_bit_array_size = ft.size |
70e191bd | 176 | |
4810b707 | 177 | self._try_append_align_action(ft.alignment, do_align, ft) |
70e191bd | 178 | |
4810b707 PP |
179 | if type(ft) is barectf_config.StructureFieldType: |
180 | for member_name, member in ft.members.items(): | |
181 | self._names.append(member_name) | |
182 | self._append_ft(member.field_type) | |
acfb8213 | 183 | del self._names[-1] |
70e191bd | 184 | else: |
4810b707 | 185 | self._append_serialize_action(ft) |
70e191bd | 186 | |
4810b707 | 187 | def _try_append_align_action(self, alignment, do_align, ft=None): |
acfb8213 PP |
188 | offset_in_byte = self._offset_in_byte |
189 | self._offset_in_byte = _align(self._offset_in_byte, alignment) % 8 | |
70e191bd | 190 | |
acfb8213 | 191 | if do_align and alignment > 1: |
4810b707 | 192 | self._actions.append(_AlignSerializationAction(offset_in_byte, ft, self._names, |
acfb8213 | 193 | alignment)) |
70e191bd | 194 | |
4810b707 PP |
195 | def _append_serialize_action(self, ft): |
196 | assert(type(ft) is not barectf_config.StructureFieldType) | |
acfb8213 PP |
197 | offset_in_byte = self._offset_in_byte |
198 | ||
4810b707 PP |
199 | if isinstance(ft, barectf_config._BitArrayFieldType): |
200 | self._offset_in_byte += ft.size | |
acfb8213 PP |
201 | self._offset_in_byte %= 8 |
202 | ||
4810b707 | 203 | self._actions.append(_SerializeSerializationAction(offset_in_byte, ft, self._names)) |
70e191bd PP |
204 | |
205 | ||
e5aa0be3 PP |
206 | _PREFIX_TPH = 'tph_' |
207 | _PREFIX_SPC = 'spc_' | |
208 | _PREFIX_SEH = 'seh_' | |
209 | _PREFIX_SEC = 'sec_' | |
210 | _PREFIX_EC = 'ec_' | |
211 | _PREFIX_EP = 'ep_' | |
acfb8213 PP |
212 | _PREFIX_TO_NAME = { |
213 | _PREFIX_TPH: 'trace packet header', | |
214 | _PREFIX_SPC: 'stream packet context', | |
215 | _PREFIX_SEH: 'stream event header', | |
216 | _PREFIX_SEC: 'stream event context', | |
217 | _PREFIX_EC: 'event context', | |
218 | _PREFIX_EP: 'event payload', | |
219 | } | |
e5aa0be3 PP |
220 | |
221 | ||
4810b707 | 222 | class _CCodeGenerator: |
e5aa0be3 PP |
223 | def __init__(self, cfg): |
224 | self._cfg = cfg | |
4810b707 PP |
225 | code_gen_opts = cfg.options.code_generation_options |
226 | self._iden_prefix = code_gen_opts.identifier_prefix | |
227 | self._cg = barectf_codegen._CodeGenerator('\t') | |
acfb8213 | 228 | self._saved_serialization_actions = {} |
e5aa0be3 | 229 | |
4810b707 PP |
230 | @property |
231 | def _trace_type(self): | |
232 | return self._cfg.trace.type | |
27bc6f1e | 233 | |
4810b707 PP |
234 | def _clk_type_c_type(self, clk_type): |
235 | return self._cfg.options.code_generation_options.clock_type_c_types[clk_type] | |
27bc6f1e | 236 | |
e5aa0be3 | 237 | def _generate_ctx_parent(self): |
4810b707 PP |
238 | tmpl = barectf_templates._CTX_PARENT |
239 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix)) | |
e5aa0be3 | 240 | |
4810b707 PP |
241 | def _generate_ctx(self, stream_type): |
242 | tmpl = barectf_templates._CTX_BEGIN | |
243 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name)) | |
244 | self._cg.indent() | |
245 | pkt_header_ft = self._trace_type._pkt_header_ft | |
e5aa0be3 | 246 | |
4810b707 PP |
247 | if pkt_header_ft is not None: |
248 | for member_name in pkt_header_ft.members: | |
249 | self._cg.add_lines(f'uint32_t off_tph_{member_name};') | |
e5aa0be3 | 250 | |
4810b707 PP |
251 | for member_name in stream_type._pkt_ctx_ft.members: |
252 | self._cg.add_lines(f'uint32_t off_spc_{member_name};') | |
27bc6f1e | 253 | |
4810b707 PP |
254 | if stream_type.default_clock_type is not None: |
255 | self._cg.add_line(f'{self._clk_type_c_type(stream_type.default_clock_type)} cur_last_event_ts;') | |
27bc6f1e | 256 | |
e5aa0be3 | 257 | self._cg.unindent() |
4810b707 | 258 | tmpl = barectf_templates._CTX_END |
e5aa0be3 PP |
259 | self._cg.add_lines(tmpl) |
260 | ||
261 | def _generate_ctxs(self): | |
4810b707 PP |
262 | for stream_type in self._trace_type.stream_types: |
263 | self._generate_ctx(stream_type) | |
e5aa0be3 | 264 | |
4810b707 PP |
265 | def _generate_clock_cb(self, clk_type): |
266 | tmpl = barectf_templates._CLOCK_CB | |
267 | self._cg.add_lines(tmpl.format(return_ctype=self._clk_type_c_type(clk_type), | |
268 | cname=clk_type.name)) | |
e5aa0be3 PP |
269 | |
270 | def _generate_clock_cbs(self): | |
4810b707 PP |
271 | clk_names = set() |
272 | ||
273 | for stream_type in self._trace_type.stream_types: | |
274 | def_clk_type = stream_type.default_clock_type | |
275 | ||
276 | if def_clk_type is not None and def_clk_type not in clk_names: | |
277 | self._generate_clock_cb(def_clk_type) | |
278 | clk_names.add(def_clk_type) | |
e5aa0be3 PP |
279 | |
280 | def _generate_platform_callbacks(self): | |
4810b707 PP |
281 | tmpl = barectf_templates._PLATFORM_CALLBACKS_BEGIN |
282 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix)) | |
e5aa0be3 PP |
283 | self._cg.indent() |
284 | self._generate_clock_cbs() | |
285 | self._cg.unindent() | |
4810b707 | 286 | tmpl = barectf_templates._PLATFORM_CALLBACKS_END |
e5aa0be3 PP |
287 | self._cg.add_lines(tmpl) |
288 | ||
289 | def generate_bitfield_header(self): | |
290 | self._cg.reset() | |
4810b707 PP |
291 | tmpl = barectf_templates._BITFIELD |
292 | tmpl = tmpl.replace('$prefix$', self._iden_prefix) | |
293 | tmpl = tmpl.replace('$PREFIX$', self._iden_prefix.upper()) | |
e5aa0be3 | 294 | |
4810b707 | 295 | if self._trace_type.default_byte_order == barectf_config.ByteOrder.BIG_ENDIAN: |
e5aa0be3 PP |
296 | endian_def = 'BIG_ENDIAN' |
297 | else: | |
298 | endian_def = 'LITTLE_ENDIAN' | |
299 | ||
300 | tmpl = tmpl.replace('$ENDIAN_DEF$', endian_def) | |
301 | self._cg.add_lines(tmpl) | |
302 | ||
303 | return self._cg.code | |
304 | ||
305 | def _generate_func_init_proto(self): | |
4810b707 PP |
306 | tmpl = barectf_templates._FUNC_INIT_PROTO |
307 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix)) | |
308 | ||
309 | def _get_ft_c_type(self, ft): | |
310 | if isinstance(ft, barectf_config._IntegerFieldType): | |
311 | sign_prefix = 'u' if isinstance(ft, barectf_config.UnsignedIntegerFieldType) else '' | |
312 | ||
313 | if ft.size <= 8: | |
314 | sz = 8 | |
315 | elif ft.size <= 16: | |
316 | sz = 16 | |
317 | elif ft.size <= 32: | |
318 | sz = 32 | |
319 | else: | |
320 | assert ft.size == 64 | |
321 | sz = 64 | |
322 | ||
323 | return f'{sign_prefix}int{sz}_t' | |
324 | elif type(ft) is barectf_config.RealFieldType: | |
325 | if ft.size == 32 and ft.alignment == 32: | |
326 | return 'float' | |
327 | elif ft.size == 64 and ft.alignment == 64: | |
328 | return 'double' | |
329 | else: | |
330 | return 'uint64_t' | |
e5aa0be3 | 331 | else: |
4810b707 PP |
332 | assert type(ft) is barectf_config.StringFieldType |
333 | return 'const char *' | |
e5aa0be3 | 334 | |
4810b707 PP |
335 | def _generate_ft_c_type(self, ft): |
336 | c_type = self._get_ft_c_type(ft) | |
337 | self._cg.append_to_last_line(c_type) | |
e5aa0be3 | 338 | |
4810b707 PP |
339 | def _generate_proto_param(self, ft, name): |
340 | self._generate_ft_c_type(ft) | |
e5aa0be3 PP |
341 | self._cg.append_to_last_line(' ') |
342 | self._cg.append_to_last_line(name) | |
343 | ||
4810b707 PP |
344 | def _generate_proto_params(self, ft, name_prefix, exclude_set=None): |
345 | if exclude_set is None: | |
346 | exclude_set = set() | |
347 | ||
e5aa0be3 PP |
348 | self._cg.indent() |
349 | ||
4810b707 PP |
350 | for member_name, member in ft.members.items(): |
351 | if member_name in exclude_set: | |
e5aa0be3 PP |
352 | continue |
353 | ||
e5aa0be3 PP |
354 | self._cg.append_to_last_line(',') |
355 | self._cg.add_line('') | |
4810b707 | 356 | self._generate_proto_param(member.field_type, name_prefix + member_name) |
e5aa0be3 PP |
357 | |
358 | self._cg.unindent() | |
359 | ||
4810b707 PP |
360 | def _generate_func_open_proto(self, stream_type): |
361 | tmpl = barectf_templates._FUNC_OPEN_PROTO_BEGIN | |
362 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name)) | |
363 | ||
364 | if self._trace_type._pkt_header_ft is not None: | |
365 | self._generate_proto_params(self._trace_type._pkt_header_ft, _PREFIX_TPH, | |
366 | {'magic', 'stream_id', 'uuid'}) | |
e5aa0be3 | 367 | |
4810b707 PP |
368 | exclude_set = { |
369 | 'timestamp_begin', | |
370 | 'timestamp_end', | |
371 | 'packet_size', | |
372 | 'content_size', | |
373 | 'events_discarded', | |
374 | } | |
375 | self._generate_proto_params(stream_type._pkt_ctx_ft, _PREFIX_SPC, exclude_set) | |
376 | tmpl = barectf_templates._FUNC_OPEN_PROTO_END | |
e5aa0be3 PP |
377 | self._cg.add_lines(tmpl) |
378 | ||
4810b707 PP |
379 | def _generate_func_close_proto(self, stream_type): |
380 | tmpl = barectf_templates._FUNC_CLOSE_PROTO | |
381 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name)) | |
e5aa0be3 | 382 | |
4810b707 PP |
383 | def _generate_func_trace_proto_params(self, stream_type, ev_type): |
384 | if stream_type._ev_header_ft is not None: | |
385 | self._generate_proto_params(stream_type._ev_header_ft, _PREFIX_SEH, {'id', 'timestamp'}) | |
386 | ||
387 | if stream_type.event_common_context_field_type is not None: | |
388 | self._generate_proto_params(stream_type.event_common_context_field_type, _PREFIX_SEC) | |
389 | ||
390 | if ev_type.specific_context_field_type is not None: | |
391 | self._generate_proto_params(ev_type.specific_context_field_type, _PREFIX_EC) | |
392 | ||
393 | if ev_type.payload_field_type is not None: | |
394 | self._generate_proto_params(ev_type.payload_field_type, _PREFIX_EP) | |
395 | ||
396 | def _generate_func_trace_proto(self, stream_type, ev_type): | |
397 | tmpl = barectf_templates._FUNC_TRACE_PROTO_BEGIN | |
398 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name, | |
399 | evname=ev_type.name)) | |
400 | self._generate_func_trace_proto_params(stream_type, ev_type) | |
401 | tmpl = barectf_templates._FUNC_TRACE_PROTO_END | |
e5aa0be3 PP |
402 | self._cg.add_lines(tmpl) |
403 | ||
404 | def _punctuate_proto(self): | |
405 | self._cg.append_to_last_line(';') | |
406 | ||
4810b707 | 407 | def generate_header(self, bitfield_header_name): |
e5aa0be3 PP |
408 | self._cg.reset() |
409 | dt = datetime.datetime.now().isoformat() | |
30c8f734 | 410 | prefix_def = '' |
4810b707 PP |
411 | def_stream_type_name_def = '' |
412 | cg_opts = self._cfg.options.code_generation_options | |
413 | header_opts = cg_opts.header_options | |
414 | ||
415 | if header_opts.identifier_prefix_definition: | |
416 | prefix_def = f'#define _BARECTF_PREFIX {self._iden_prefix}' | |
30c8f734 | 417 | |
4810b707 | 418 | def_stream_type = cg_opts.default_stream_type |
30c8f734 | 419 | |
4810b707 PP |
420 | if header_opts.default_stream_type_name_definition and def_stream_type is not None: |
421 | def_stream_type_name_def = f'#define _BARECTF_DEFAULT_STREAM {def_stream_type.name}' | |
30c8f734 | 422 | |
4810b707 | 423 | def_stream_type_trace_defs = '' |
a50674ee | 424 | |
4810b707 | 425 | if def_stream_type is not None: |
a50674ee PP |
426 | lines = [] |
427 | ||
4810b707 PP |
428 | for ev_type in def_stream_type.event_types: |
429 | tmpl = barectf_templates._DEFINE_DEFAULT_STREAM_TRACE | |
430 | define = tmpl.format(prefix=self._iden_prefix, sname=def_stream_type.name, | |
431 | evname=ev_type.name) | |
a50674ee PP |
432 | lines.append(define) |
433 | ||
4810b707 | 434 | def_stream_type_trace_defs = '\n'.join(lines) |
a50674ee | 435 | |
4810b707 PP |
436 | tmpl = barectf_templates._HEADER_BEGIN |
437 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, | |
438 | ucprefix=self._iden_prefix.upper(), | |
439 | bitfield_header_filename=bitfield_header_name, | |
440 | version=barectf_version.__version__, date=dt, | |
30c8f734 | 441 | prefix_def=prefix_def, |
4810b707 PP |
442 | default_stream_def=def_stream_type_name_def, |
443 | default_stream_trace_defs=def_stream_type_trace_defs)) | |
e5aa0be3 PP |
444 | self._cg.add_empty_line() |
445 | ||
446 | # platform callbacks structure | |
447 | self._generate_platform_callbacks() | |
448 | self._cg.add_empty_line() | |
449 | ||
450 | # context parent | |
451 | self._generate_ctx_parent() | |
452 | self._cg.add_empty_line() | |
453 | ||
454 | # stream contexts | |
455 | self._generate_ctxs() | |
456 | self._cg.add_empty_line() | |
457 | ||
458 | # initialization function prototype | |
459 | self._generate_func_init_proto() | |
460 | self._punctuate_proto() | |
461 | self._cg.add_empty_line() | |
462 | ||
4810b707 PP |
463 | for stream_type in self._trace_type.stream_types: |
464 | self._generate_func_open_proto(stream_type) | |
e5aa0be3 PP |
465 | self._punctuate_proto() |
466 | self._cg.add_empty_line() | |
4810b707 | 467 | self._generate_func_close_proto(stream_type) |
e5aa0be3 PP |
468 | self._punctuate_proto() |
469 | self._cg.add_empty_line() | |
470 | ||
4810b707 PP |
471 | for ev_type in stream_type.event_types: |
472 | self._generate_func_trace_proto(stream_type, ev_type) | |
e5aa0be3 PP |
473 | self._punctuate_proto() |
474 | self._cg.add_empty_line() | |
475 | ||
4810b707 PP |
476 | tmpl = barectf_templates._HEADER_END |
477 | self._cg.add_lines(tmpl.format(ucprefix=self._iden_prefix.upper())) | |
e5aa0be3 PP |
478 | return self._cg.code |
479 | ||
4810b707 PP |
480 | def _get_call_event_param_list_from_struct_ft(self, ft, prefix, exclude_set=None): |
481 | if exclude_set is None: | |
482 | exclude_set = set() | |
483 | ||
e5aa0be3 PP |
484 | lst = '' |
485 | ||
4810b707 PP |
486 | for member_name in ft.members: |
487 | if member_name in exclude_set: | |
e5aa0be3 PP |
488 | continue |
489 | ||
4810b707 | 490 | lst += f', {prefix}{member_name}' |
e5aa0be3 PP |
491 | |
492 | return lst | |
493 | ||
4810b707 | 494 | def _get_call_event_param_list(self, stream_type, ev_type): |
e5aa0be3 | 495 | lst = '' |
e5aa0be3 | 496 | |
4810b707 PP |
497 | if stream_type._ev_header_ft is not None: |
498 | lst += self._get_call_event_param_list_from_struct_ft(stream_type._ev_header_ft, | |
499 | _PREFIX_SEH, {'id', 'timestamp'}) | |
e5aa0be3 | 500 | |
4810b707 PP |
501 | if stream_type.event_common_context_field_type is not None: |
502 | lst += self._get_call_event_param_list_from_struct_ft(stream_type.event_common_context_field_type, | |
503 | _PREFIX_SEC) | |
e5aa0be3 | 504 | |
4810b707 PP |
505 | if ev_type.specific_context_field_type is not None: |
506 | lst += self._get_call_event_param_list_from_struct_ft(ev_type.specific_context_field_type, | |
507 | _PREFIX_EC) | |
e5aa0be3 | 508 | |
4810b707 PP |
509 | if ev_type.payload_field_type is not None: |
510 | lst += self._get_call_event_param_list_from_struct_ft(ev_type.payload_field_type, | |
511 | _PREFIX_EP) | |
e5aa0be3 PP |
512 | |
513 | return lst | |
514 | ||
515 | def _generate_align(self, at, align): | |
4810b707 | 516 | self._cg.add_line(f'_ALIGN({at}, {align});') |
e5aa0be3 PP |
517 | |
518 | def _generate_incr_pos(self, var, value): | |
4810b707 | 519 | self._cg.add_line(f'{var} += {value};') |
e5aa0be3 PP |
520 | |
521 | def _generate_incr_pos_bytes(self, var, value): | |
4810b707 PP |
522 | self._generate_incr_pos(var, f'_BYTES_TO_BITS({value})') |
523 | ||
524 | def _generate_func_get_event_size_proto(self, stream_type, ev_type): | |
525 | tmpl = barectf_templates._FUNC_GET_EVENT_SIZE_PROTO_BEGIN | |
526 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name, | |
527 | evname=ev_type.name)) | |
528 | self._generate_func_trace_proto_params(stream_type, ev_type) | |
529 | tmpl = barectf_templates._FUNC_GET_EVENT_SIZE_PROTO_END | |
e5aa0be3 PP |
530 | self._cg.add_lines(tmpl) |
531 | ||
4810b707 PP |
532 | def _generate_func_get_event_size(self, stream_type, ev_type): |
533 | self._generate_func_get_event_size_proto(stream_type, ev_type) | |
534 | tmpl = barectf_templates._FUNC_GET_EVENT_SIZE_BODY_BEGIN | |
535 | lines = tmpl.format(prefix=self._iden_prefix) | |
f66be07f | 536 | self._cg.add_lines(lines) |
e5aa0be3 PP |
537 | self._cg.add_empty_line() |
538 | self._cg.indent() | |
acfb8213 | 539 | ser_actions = _SerializationActions() |
4810b707 PP |
540 | ser_actions.append_root_scope_ft(stream_type._ev_header_ft, _PREFIX_SEH) |
541 | ser_actions.append_root_scope_ft(stream_type.event_common_context_field_type, _PREFIX_SEC) | |
542 | ser_actions.append_root_scope_ft(ev_type.specific_context_field_type, _PREFIX_EC) | |
543 | ser_actions.append_root_scope_ft(ev_type.payload_field_type, _PREFIX_EP) | |
acfb8213 PP |
544 | |
545 | for action in ser_actions.actions: | |
546 | if type(action) is _AlignSerializationAction: | |
547 | if action.names: | |
548 | if len(action.names) == 1: | |
4810b707 | 549 | line = f'align {_PREFIX_TO_NAME[action.names[0]]} structure' |
acfb8213 | 550 | else: |
4810b707 | 551 | line = f'align field `{action.names[-1]}` ({_PREFIX_TO_NAME[action.names[0]]})' |
acfb8213 PP |
552 | |
553 | self._cg.add_cc_line(line) | |
554 | ||
555 | self._generate_align('at', action.value) | |
556 | self._cg.add_empty_line() | |
4810b707 PP |
557 | else: |
558 | assert type(action) is _SerializeSerializationAction | |
acfb8213 | 559 | assert(len(action.names) >= 2) |
4810b707 | 560 | line = f'add size of field `{action.names[-1]}` ({_PREFIX_TO_NAME[action.names[0]]})' |
acfb8213 PP |
561 | self._cg.add_cc_line(line) |
562 | ||
4810b707 | 563 | if type(action.ft) is barectf_config.StringFieldType: |
acfb8213 | 564 | param = ''.join(action.names) |
4810b707 | 565 | self._generate_incr_pos_bytes('at', f'strlen({param}) + 1') |
acfb8213 | 566 | else: |
4810b707 | 567 | self._generate_incr_pos('at', action.ft.size) |
e5aa0be3 | 568 | |
acfb8213 | 569 | self._cg.add_empty_line() |
70e191bd | 570 | |
e5aa0be3 | 571 | self._cg.unindent() |
4810b707 | 572 | tmpl = barectf_templates._FUNC_GET_EVENT_SIZE_BODY_END |
e5aa0be3 PP |
573 | self._cg.add_lines(tmpl) |
574 | ||
4810b707 PP |
575 | def _generate_func_serialize_event_proto(self, stream_type, ev_type): |
576 | tmpl = barectf_templates._FUNC_SERIALIZE_EVENT_PROTO_BEGIN | |
577 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name, | |
578 | evname=ev_type.name)) | |
579 | self._generate_func_trace_proto_params(stream_type, ev_type) | |
580 | tmpl = barectf_templates._FUNC_SERIALIZE_EVENT_PROTO_END | |
e5aa0be3 PP |
581 | self._cg.add_lines(tmpl) |
582 | ||
4810b707 PP |
583 | def _generate_serialize_from_action(self, var, ctx, action): |
584 | def gen_bitfield_write(c_type, var, ctx, action): | |
585 | ptr = f'&{ctx}->buf[_BITS_TO_BYTES({ctx}->at)]' | |
586 | start = action.offset_in_byte | |
587 | suffix = 'le' if action.ft.byte_order is barectf_config.ByteOrder.LITTLE_ENDIAN else 'be' | |
588 | func = f'{self._iden_prefix}bt_bitfield_write_{suffix}' | |
589 | call = f'{func}({ptr}, uint8_t, {start}, {action.ft.size}, {c_type}, ({c_type}) {var});' | |
590 | self._cg.add_line(call) | |
591 | ||
592 | def gen_serialize_int(var, ctx, action): | |
593 | c_type = self._get_ft_c_type(action.ft) | |
594 | gen_bitfield_write(c_type, var, ctx, action) | |
595 | self._generate_incr_pos(f'{ctx}->at', action.ft.size) | |
596 | ||
597 | def gen_serialize_real(var, ctx, action): | |
598 | c_type = self._get_ft_c_type(action.ft) | |
599 | flt_dbl = False | |
600 | ||
601 | if c_type == 'float' or c_type == 'double': | |
602 | flt_dbl = True | |
603 | ||
604 | if c_type == 'float': | |
605 | union_name = 'f2u' | |
606 | int_c_type = 'uint32_t' | |
607 | else: | |
608 | assert c_type == 'double' | |
609 | union_name = 'd2u' | |
610 | int_c_type = 'uint64_t' | |
1405552b | 611 | |
4810b707 PP |
612 | # union for reading the bytes of the floating point number |
613 | self._cg.add_empty_line() | |
614 | self._cg.add_line('{') | |
615 | self._cg.indent() | |
616 | self._cg.add_line(f'union {union_name} {union_name};') | |
617 | self._cg.add_empty_line() | |
618 | self._cg.add_line(f'{union_name}.f = {var};') | |
619 | bf_var = f'{union_name}.u' | |
620 | else: | |
621 | bf_var = f'({c_type}) {var}' | |
622 | int_c_type = c_type | |
7656a395 | 623 | |
4810b707 | 624 | gen_bitfield_write(int_c_type, bf_var, ctx, action) |
7656a395 | 625 | |
4810b707 PP |
626 | if flt_dbl: |
627 | self._cg.unindent() | |
628 | self._cg.add_line('}') | |
629 | self._cg.add_empty_line() | |
e5aa0be3 | 630 | |
4810b707 | 631 | self._generate_incr_pos(f'{ctx}->at', action.ft.size) |
e5aa0be3 | 632 | |
4810b707 PP |
633 | def gen_serialize_string(var, ctx, action): |
634 | self._cg.add_lines(f'_write_cstring({ctx}, {var});') | |
e5aa0be3 | 635 | |
4810b707 PP |
636 | if isinstance(action.ft, barectf_config._IntegerFieldType): |
637 | return gen_serialize_int(var, ctx, action) | |
638 | elif type(action.ft) is barectf_config.RealFieldType: | |
639 | return gen_serialize_real(var, ctx, action) | |
640 | else: | |
641 | assert type(action.ft) is barectf_config.StringFieldType | |
642 | return gen_serialize_string(var, ctx, action) | |
acfb8213 | 643 | |
4810b707 | 644 | def _generate_serialize_statements_from_actions(self, prefix, action_iter, spec_src=None): |
acfb8213 PP |
645 | for action in action_iter: |
646 | if type(action) is _AlignSerializationAction: | |
647 | if action.names: | |
648 | if len(action.names) == 1: | |
4810b707 | 649 | line = f'align {_PREFIX_TO_NAME[action.names[0]]} structure' |
acfb8213 | 650 | else: |
4810b707 | 651 | line = f'align field `{action.names[-1]}` ({_PREFIX_TO_NAME[action.names[0]]})' |
acfb8213 PP |
652 | |
653 | self._cg.add_cc_line(line) | |
654 | ||
655 | self._generate_align('ctx->at', action.value) | |
656 | self._cg.add_empty_line() | |
4810b707 PP |
657 | else: |
658 | assert type(action) is _SerializeSerializationAction | |
acfb8213 | 659 | assert(len(action.names) >= 2) |
4810b707 PP |
660 | member_name = action.names[-1] |
661 | line = f'serialize field `{member_name}` ({_PREFIX_TO_NAME[action.names[0]]})' | |
acfb8213 | 662 | self._cg.add_cc_line(line) |
4810b707 | 663 | src = prefix + member_name |
acfb8213 | 664 | |
4810b707 PP |
665 | if spec_src is not None and member_name in spec_src: |
666 | src = spec_src[member_name] | |
e5aa0be3 | 667 | |
acfb8213 PP |
668 | self._generate_serialize_from_action(src, 'ctx', action) |
669 | self._cg.add_empty_line() | |
e5aa0be3 | 670 | |
4810b707 PP |
671 | def _generate_func_serialize_event(self, stream_type, ev_type, orig_ser_actions): |
672 | self._generate_func_serialize_event_proto(stream_type, ev_type) | |
673 | tmpl = barectf_templates._FUNC_SERIALIZE_EVENT_BODY_BEGIN | |
674 | lines = tmpl.format(prefix=self._iden_prefix) | |
f66be07f | 675 | self._cg.add_lines(lines) |
e5aa0be3 | 676 | self._cg.indent() |
3cb793a1 | 677 | self._cg.add_empty_line() |
e5aa0be3 | 678 | |
4810b707 PP |
679 | if stream_type._ev_header_ft is not None: |
680 | params = self._get_call_event_param_list_from_struct_ft(stream_type._ev_header_ft, | |
681 | _PREFIX_SEH, | |
682 | {'timestamp', 'id'}) | |
e5aa0be3 | 683 | self._cg.add_cc_line('stream event header') |
4810b707 PP |
684 | line = f'_serialize_stream_event_header_{stream_type.name}(ctx, {ev_type.id}{params});' |
685 | self._cg.add_line(line) | |
e5aa0be3 PP |
686 | self._cg.add_empty_line() |
687 | ||
4810b707 PP |
688 | if stream_type.event_common_context_field_type is not None: |
689 | params = self._get_call_event_param_list_from_struct_ft(stream_type.event_common_context_field_type, | |
690 | _PREFIX_SEC) | |
e5aa0be3 | 691 | self._cg.add_cc_line('stream event context') |
4810b707 PP |
692 | line = f'_serialize_stream_event_context_{stream_type.name}(ctx{params});' |
693 | self._cg.add_line(line) | |
e5aa0be3 PP |
694 | self._cg.add_empty_line() |
695 | ||
4810b707 | 696 | if ev_type.specific_context_field_type is not None or ev_type.payload_field_type is not None: |
acfb8213 PP |
697 | ser_actions = copy.deepcopy(orig_ser_actions) |
698 | ||
4810b707 | 699 | if ev_type.specific_context_field_type is not None: |
acfb8213 | 700 | ser_action_index = len(ser_actions.actions) |
4810b707 PP |
701 | ser_actions.append_root_scope_ft(ev_type.specific_context_field_type, _PREFIX_EC) |
702 | ser_action_iter = itertools.islice(ser_actions.actions, ser_action_index, None) | |
703 | self._generate_serialize_statements_from_actions(_PREFIX_EC, ser_action_iter) | |
e5aa0be3 | 704 | |
4810b707 | 705 | if ev_type.payload_field_type is not None: |
acfb8213 | 706 | ser_action_index = len(ser_actions.actions) |
4810b707 PP |
707 | ser_actions.append_root_scope_ft(ev_type.payload_field_type, _PREFIX_EP) |
708 | ser_action_iter = itertools.islice(ser_actions.actions, ser_action_index, None) | |
709 | self._generate_serialize_statements_from_actions(_PREFIX_EP, ser_action_iter) | |
e5aa0be3 PP |
710 | |
711 | self._cg.unindent() | |
4810b707 | 712 | tmpl = barectf_templates._FUNC_SERIALIZE_EVENT_BODY_END |
e5aa0be3 PP |
713 | self._cg.add_lines(tmpl) |
714 | ||
4810b707 PP |
715 | def _generate_func_serialize_event_header_proto(self, stream_type): |
716 | tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_BEGIN | |
717 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name)) | |
e5aa0be3 | 718 | |
4810b707 PP |
719 | if stream_type._ev_header_ft is not None: |
720 | self._generate_proto_params(stream_type._ev_header_ft, _PREFIX_SEH, | |
721 | {'id', 'timestamp'}) | |
e5aa0be3 | 722 | |
4810b707 | 723 | tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_END |
e5aa0be3 PP |
724 | self._cg.add_lines(tmpl) |
725 | ||
4810b707 PP |
726 | def _generate_func_serialize_event_common_context_proto(self, stream_type): |
727 | tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_BEGIN | |
728 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, sname=stream_type.name)) | |
e5aa0be3 | 729 | |
4810b707 PP |
730 | if stream_type.event_common_context_field_type is not None: |
731 | self._generate_proto_params(stream_type.event_common_context_field_type, _PREFIX_SEC) | |
e5aa0be3 | 732 | |
4810b707 | 733 | tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_END |
e5aa0be3 PP |
734 | self._cg.add_lines(tmpl) |
735 | ||
4810b707 PP |
736 | def _generate_func_serialize_event_header(self, stream_type, ser_action_iter): |
737 | self._generate_func_serialize_event_header_proto(stream_type) | |
738 | tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_BEGIN | |
739 | lines = tmpl.format(prefix=self._iden_prefix, sname=stream_type.name) | |
f66be07f | 740 | self._cg.add_lines(lines) |
e5aa0be3 | 741 | self._cg.indent() |
27bc6f1e | 742 | |
4810b707 PP |
743 | if stream_type.default_clock_type is not None: |
744 | line = f'struct {self._iden_prefix}{stream_type.name}_ctx *s_ctx = FROM_VOID_PTR(struct {self._iden_prefix}{stream_type.name}_ctx, vctx);' | |
27bc6f1e | 745 | self._cg.add_line(line) |
4810b707 | 746 | line = f'const {self._clk_type_c_type(stream_type.default_clock_type)} ts = s_ctx->cur_last_event_ts;' |
27bc6f1e PP |
747 | self._cg.add_line(line) |
748 | ||
e5aa0be3 | 749 | self._cg.add_empty_line() |
e5aa0be3 | 750 | |
4810b707 | 751 | if stream_type._ev_header_ft is not None: |
e5aa0be3 | 752 | spec_src = {} |
4810b707 PP |
753 | member_name = 'id' |
754 | member = stream_type._ev_header_ft.members.get(member_name) | |
755 | ||
756 | if member is not None: | |
757 | spec_src[member_name] = f'({self._get_ft_c_type(member.field_type)}) event_id' | |
e5aa0be3 | 758 | |
4810b707 PP |
759 | member_name = 'timestamp' |
760 | member = stream_type._ev_header_ft.members.get(member_name) | |
e5aa0be3 | 761 | |
4810b707 PP |
762 | if member is not None: |
763 | spec_src[member_name] = f'({self._get_ft_c_type(member.field_type)}) ts' | |
e5aa0be3 | 764 | |
4810b707 | 765 | self._generate_serialize_statements_from_actions(_PREFIX_SEH, ser_action_iter, |
acfb8213 | 766 | spec_src) |
e5aa0be3 PP |
767 | |
768 | self._cg.unindent() | |
4810b707 | 769 | tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_END |
e5aa0be3 PP |
770 | self._cg.add_lines(tmpl) |
771 | ||
4810b707 PP |
772 | def _generate_func_serialize_event_common_context(self, stream_type, ser_action_iter): |
773 | self._generate_func_serialize_event_common_context_proto(stream_type) | |
774 | tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_BEGIN | |
775 | lines = tmpl.format(prefix=self._iden_prefix) | |
f66be07f | 776 | self._cg.add_lines(lines) |
e5aa0be3 | 777 | self._cg.indent() |
e5aa0be3 | 778 | |
4810b707 PP |
779 | if stream_type.event_common_context_field_type is not None: |
780 | self._generate_serialize_statements_from_actions(_PREFIX_SEC, ser_action_iter) | |
e5aa0be3 PP |
781 | |
782 | self._cg.unindent() | |
4810b707 | 783 | tmpl = barectf_templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_END |
e5aa0be3 PP |
784 | self._cg.add_lines(tmpl) |
785 | ||
4810b707 PP |
786 | def _generate_func_trace(self, stream_type, ev_type): |
787 | self._generate_func_trace_proto(stream_type, ev_type) | |
788 | params = self._get_call_event_param_list(stream_type, ev_type) | |
789 | def_clk_type = stream_type.default_clock_type | |
3cb793a1 | 790 | |
4810b707 PP |
791 | if def_clk_type is not None: |
792 | save_ts_line = f'ctx->cur_last_event_ts = ctx->parent.cbs.{def_clk_type.name}_clock_get_value(ctx->parent.data);' | |
27bc6f1e PP |
793 | else: |
794 | save_ts_line = '/* (no clock) */' | |
3cb793a1 | 795 | |
4810b707 PP |
796 | tmpl = barectf_templates._FUNC_TRACE_BODY |
797 | self._cg.add_lines(tmpl.format(sname=stream_type.name, evname=ev_type.name, params=params, | |
798 | save_ts=save_ts_line)) | |
e5aa0be3 PP |
799 | |
800 | def _generate_func_init(self): | |
801 | self._generate_func_init_proto() | |
4810b707 PP |
802 | tmpl = barectf_templates._FUNC_INIT_BODY |
803 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix)) | |
e5aa0be3 | 804 | |
4810b707 PP |
805 | def _generate_member_name_cc_line(self, member_name): |
806 | self._cg.add_cc_line(f'`{member_name}` field') | |
e5aa0be3 | 807 | |
acfb8213 PP |
808 | def _save_serialization_action(self, name, action): |
809 | self._saved_serialization_actions[name] = action | |
1405552b | 810 | |
4810b707 PP |
811 | def _get_open_close_ts_line(self, stream_type): |
812 | def_clk_type = stream_type.default_clock_type | |
3cb793a1 | 813 | |
4810b707 | 814 | if def_clk_type is None: |
3cb793a1 PP |
815 | return '' |
816 | ||
4810b707 PP |
817 | c_type = self._clk_type_c_type(def_clk_type) |
818 | return f'\tconst {c_type} ts = ctx->parent.use_cur_last_event_ts ? ctx->cur_last_event_ts : ctx->parent.cbs.{def_clk_type.name}_clock_get_value(ctx->parent.data);' | |
3cb793a1 | 819 | |
4810b707 | 820 | def _generate_func_open(self, stream_type): |
acfb8213 | 821 | def generate_save_offset(name, action): |
4810b707 | 822 | self._cg.add_line(f'ctx->off_spc_{name} = ctx->parent.at;') |
acfb8213 | 823 | self._save_serialization_action(name, action) |
e5aa0be3 | 824 | |
4810b707 PP |
825 | self._generate_func_open_proto(stream_type) |
826 | tmpl = barectf_templates._FUNC_OPEN_BODY_BEGIN | |
827 | pkt_ctx_ft = stream_type._pkt_ctx_ft | |
828 | ts_line = self._get_open_close_ts_line(stream_type) | |
3cb793a1 PP |
829 | lines = tmpl.format(ts=ts_line) |
830 | self._cg.add_lines(lines) | |
831 | self._cg.indent() | |
e5aa0be3 PP |
832 | self._cg.add_cc_line('do not open a packet that is already open') |
833 | self._cg.add_line('if (ctx->parent.packet_is_open) {') | |
834 | self._cg.indent() | |
3cb793a1 | 835 | self._cg.add_line('ctx->parent.in_tracing_section = saved_in_tracing_section;') |
e5aa0be3 PP |
836 | self._cg.add_line('return;') |
837 | self._cg.unindent() | |
838 | self._cg.add_line('}') | |
839 | self._cg.add_empty_line() | |
840 | self._cg.add_line('ctx->parent.at = 0;') | |
4810b707 | 841 | pkt_header_ft = self._trace_type._pkt_header_ft |
acfb8213 | 842 | ser_actions = _SerializationActions() |
e5aa0be3 | 843 | |
4810b707 | 844 | if pkt_header_ft is not None: |
e5aa0be3 PP |
845 | self._cg.add_empty_line() |
846 | self._cg.add_cc_line('trace packet header') | |
847 | self._cg.add_line('{') | |
848 | self._cg.indent() | |
4810b707 | 849 | ser_actions.append_root_scope_ft(pkt_header_ft, _PREFIX_TPH) |
e5aa0be3 | 850 | |
acfb8213 PP |
851 | for action in ser_actions.actions: |
852 | if type(action) is _AlignSerializationAction: | |
853 | if action.names: | |
854 | if len(action.names) == 1: | |
855 | line = 'align trace packet header structure' | |
856 | else: | |
4810b707 | 857 | line = f'align field `{action.names[-1]}`' |
e5aa0be3 | 858 | |
acfb8213 | 859 | self._cg.add_cc_line(line) |
e5aa0be3 | 860 | |
acfb8213 PP |
861 | self._generate_align('ctx->parent.at', action.value) |
862 | self._cg.add_empty_line() | |
4810b707 PP |
863 | else: |
864 | assert type(action) is _SerializeSerializationAction | |
acfb8213 | 865 | assert(len(action.names) >= 2) |
4810b707 PP |
866 | member_name = action.names[-1] |
867 | line = f'serialize field `{member_name}`' | |
acfb8213 | 868 | self._cg.add_cc_line(line) |
4810b707 | 869 | src = _PREFIX_TPH + member_name |
acfb8213 | 870 | |
4810b707 | 871 | if member_name == 'magic': |
acfb8213 | 872 | src = '0xc1fc1fc1UL' |
4810b707 PP |
873 | elif member_name == 'stream_id': |
874 | src = f'({self._get_ft_c_type(action.ft)}) {stream_type.id}' | |
875 | elif member_name == 'uuid': | |
acfb8213 PP |
876 | self._cg.add_line('{') |
877 | self._cg.indent() | |
878 | self._cg.add_line('static uint8_t uuid[] = {') | |
879 | self._cg.indent() | |
880 | ||
4810b707 PP |
881 | for b in self._trace_type.uuid.bytes: |
882 | self._cg.add_line(f'{b},') | |
acfb8213 PP |
883 | |
884 | self._cg.unindent() | |
885 | self._cg.add_line('};') | |
886 | self._cg.add_empty_line() | |
887 | self._generate_align('ctx->parent.at', 8) | |
888 | line = 'memcpy(&ctx->parent.buf[_BITS_TO_BYTES(ctx->parent.at)], uuid, 16);' | |
889 | self._cg.add_line(line) | |
890 | self._generate_incr_pos_bytes('ctx->parent.at', 16) | |
891 | self._cg.unindent() | |
892 | self._cg.add_line('}') | |
893 | self._cg.add_empty_line() | |
894 | continue | |
895 | ||
896 | self._generate_serialize_from_action(src, '(&ctx->parent)', action) | |
897 | self._cg.add_empty_line() | |
e5aa0be3 PP |
898 | |
899 | self._cg.unindent() | |
900 | self._cg.add_lines('}') | |
901 | ||
acfb8213 | 902 | spc_action_index = len(ser_actions.actions) |
4810b707 PP |
903 | self._cg.add_empty_line() |
904 | self._cg.add_cc_line('stream packet context') | |
905 | self._cg.add_line('{') | |
906 | self._cg.indent() | |
907 | ser_actions.append_root_scope_ft(pkt_ctx_ft, _PREFIX_SPC) | |
acfb8213 | 908 | |
4810b707 PP |
909 | for action in itertools.islice(ser_actions.actions, spc_action_index, None): |
910 | if type(action) is _AlignSerializationAction: | |
911 | if action.names: | |
912 | if len(action.names) == 1: | |
913 | line = 'align stream packet context structure' | |
914 | else: | |
915 | line = f'align field `{action.names[-1]}`' | |
acfb8213 | 916 | |
acfb8213 | 917 | self._cg.add_cc_line(line) |
acfb8213 | 918 | |
4810b707 PP |
919 | self._generate_align('ctx->parent.at', action.value) |
920 | self._cg.add_empty_line() | |
921 | else: | |
922 | assert type(action) is _SerializeSerializationAction | |
923 | assert(len(action.names) >= 2) | |
924 | member_name = action.names[-1] | |
925 | line = f'serialize field `{member_name}`' | |
926 | self._cg.add_cc_line(line) | |
927 | src = _PREFIX_SPC + member_name | |
928 | skip_int = False | |
929 | ||
930 | if member_name == 'timestamp_begin': | |
931 | src = f'({self._get_ft_c_type(action.ft)}) ts' | |
932 | elif member_name in {'timestamp_end', 'content_size', 'events_discarded'}: | |
933 | skip_int = True | |
934 | elif member_name == 'packet_size': | |
935 | src = f'({self._get_ft_c_type(action.ft)}) ctx->parent.packet_size' | |
936 | ||
937 | if skip_int: | |
938 | generate_save_offset(member_name, action) | |
939 | self._generate_incr_pos('ctx->parent.at', action.ft.size) | |
940 | else: | |
941 | self._generate_serialize_from_action(src, '(&ctx->parent)', action) | |
e5aa0be3 | 942 | |
4810b707 | 943 | self._cg.add_empty_line() |
e5aa0be3 PP |
944 | |
945 | self._cg.unindent() | |
4810b707 PP |
946 | self._cg.add_lines('}') |
947 | self._cg.unindent() | |
948 | tmpl = barectf_templates._FUNC_OPEN_BODY_END | |
e5aa0be3 PP |
949 | self._cg.add_lines(tmpl) |
950 | ||
4810b707 | 951 | def _generate_func_close(self, stream_type): |
e5aa0be3 | 952 | def generate_goto_offset(name): |
4810b707 | 953 | self._cg.add_line(f'ctx->parent.at = ctx->off_spc_{name};') |
e5aa0be3 | 954 | |
4810b707 PP |
955 | self._generate_func_close_proto(stream_type) |
956 | tmpl = barectf_templates._FUNC_CLOSE_BODY_BEGIN | |
957 | pkt_ctx_ft = stream_type._pkt_ctx_ft | |
958 | ts_line = self._get_open_close_ts_line(stream_type) | |
3cb793a1 PP |
959 | lines = tmpl.format(ts=ts_line) |
960 | self._cg.add_lines(lines) | |
961 | self._cg.indent() | |
e5aa0be3 PP |
962 | self._cg.add_cc_line('do not close a packet that is not open') |
963 | self._cg.add_line('if (!ctx->parent.packet_is_open) {') | |
964 | self._cg.indent() | |
3cb793a1 | 965 | self._cg.add_line('ctx->parent.in_tracing_section = saved_in_tracing_section;') |
e5aa0be3 PP |
966 | self._cg.add_line('return;') |
967 | self._cg.unindent() | |
968 | self._cg.add_line('}') | |
969 | self._cg.add_empty_line() | |
970 | self._cg.add_cc_line('save content size') | |
971 | self._cg.add_line('ctx->parent.content_size = ctx->parent.at;') | |
4810b707 PP |
972 | member_name = 'timestamp_end' |
973 | member = pkt_ctx_ft.members.get(member_name) | |
e5aa0be3 | 974 | |
4810b707 PP |
975 | if member is not None: |
976 | self._cg.add_empty_line() | |
977 | self._generate_member_name_cc_line(member_name) | |
978 | generate_goto_offset(member_name) | |
979 | action = self._saved_serialization_actions[member_name] | |
980 | c_type = self._get_ft_c_type(member.field_type) | |
981 | self._generate_serialize_from_action(f'({c_type}) ts', '(&ctx->parent)', action) | |
e5aa0be3 | 982 | |
4810b707 PP |
983 | member_name = 'content_size' |
984 | member = pkt_ctx_ft.members.get(member_name) | |
e5aa0be3 | 985 | |
4810b707 PP |
986 | if member is not None: |
987 | self._cg.add_empty_line() | |
988 | self._generate_member_name_cc_line(member_name) | |
989 | generate_goto_offset(member_name) | |
990 | action = self._saved_serialization_actions[member_name] | |
991 | c_type = self._get_ft_c_type(member.field_type) | |
992 | self._generate_serialize_from_action(f'({c_type}) ctx->parent.content_size', | |
993 | '(&ctx->parent)', action) | |
e5aa0be3 | 994 | |
4810b707 PP |
995 | member_name = 'events_discarded' |
996 | member = pkt_ctx_ft.members.get(member_name) | |
e5aa0be3 | 997 | |
4810b707 PP |
998 | if member is not None: |
999 | self._cg.add_empty_line() | |
1000 | self._generate_member_name_cc_line(member_name) | |
1001 | generate_goto_offset(member_name) | |
1002 | action = self._saved_serialization_actions[member_name] | |
1003 | c_type = self._get_ft_c_type(member.field_type) | |
1004 | self._generate_serialize_from_action(f'({c_type}) ctx->parent.events_discarded', | |
1005 | '(&ctx->parent)', action) | |
e5aa0be3 PP |
1006 | |
1007 | self._cg.unindent() | |
4810b707 | 1008 | tmpl = barectf_templates._FUNC_CLOSE_BODY_END |
e5aa0be3 | 1009 | self._cg.add_lines(tmpl) |
e5aa0be3 | 1010 | |
4810b707 | 1011 | def generate_c_src(self, header_name): |
e5aa0be3 PP |
1012 | self._cg.reset() |
1013 | dt = datetime.datetime.now().isoformat() | |
4810b707 PP |
1014 | tmpl = barectf_templates._C_SRC |
1015 | self._cg.add_lines(tmpl.format(prefix=self._iden_prefix, header_filename=header_name, | |
1016 | version=barectf_version.__version__, date=dt)) | |
e5aa0be3 PP |
1017 | self._cg.add_empty_line() |
1018 | ||
1019 | # initialization function | |
1020 | self._generate_func_init() | |
1021 | self._cg.add_empty_line() | |
1022 | ||
4810b707 PP |
1023 | for stream_type in self._trace_type.stream_types: |
1024 | self._generate_func_open(stream_type) | |
e5aa0be3 | 1025 | self._cg.add_empty_line() |
4810b707 | 1026 | self._generate_func_close(stream_type) |
e5aa0be3 | 1027 | self._cg.add_empty_line() |
acfb8213 | 1028 | ser_actions = _SerializationActions() |
e5aa0be3 | 1029 | |
4810b707 PP |
1030 | if stream_type._ev_header_ft is not None: |
1031 | ser_actions.append_root_scope_ft(stream_type._ev_header_ft, _PREFIX_SEH) | |
1032 | self._generate_func_serialize_event_header(stream_type, iter(ser_actions.actions)) | |
e5aa0be3 PP |
1033 | self._cg.add_empty_line() |
1034 | ||
4810b707 | 1035 | if stream_type.event_common_context_field_type is not None: |
acfb8213 | 1036 | ser_action_index = len(ser_actions.actions) |
4810b707 PP |
1037 | ser_actions.append_root_scope_ft(stream_type.event_common_context_field_type, |
1038 | _PREFIX_SEC) | |
1039 | ser_action_iter = itertools.islice(ser_actions.actions, ser_action_index, None) | |
1040 | self._generate_func_serialize_event_common_context(stream_type, ser_action_iter) | |
e5aa0be3 PP |
1041 | self._cg.add_empty_line() |
1042 | ||
4810b707 PP |
1043 | for ev_type in stream_type.event_types: |
1044 | self._generate_func_get_event_size(stream_type, ev_type) | |
e5aa0be3 | 1045 | self._cg.add_empty_line() |
4810b707 | 1046 | self._generate_func_serialize_event(stream_type, ev_type, ser_actions) |
e5aa0be3 | 1047 | self._cg.add_empty_line() |
4810b707 | 1048 | self._generate_func_trace(stream_type, ev_type) |
e5aa0be3 PP |
1049 | self._cg.add_empty_line() |
1050 | ||
e5aa0be3 | 1051 | return self._cg.code |