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 PP |
23 | |
24 | from barectf import templates | |
25 | from barectf import metadata | |
26 | import barectf.codegen | |
27 | import collections | |
acfb8213 | 28 | import itertools |
e5aa0be3 PP |
29 | import argparse |
30 | import datetime | |
31 | import barectf | |
acfb8213 | 32 | import copy |
e5aa0be3 PP |
33 | import sys |
34 | import os | |
35 | import re | |
36 | ||
37 | ||
70e191bd PP |
38 | def _align(v, align): |
39 | return (v + (align - 1)) & -align | |
40 | ||
41 | ||
acfb8213 PP |
42 | class _SerializationAction: |
43 | def __init__(self, offset_in_byte, type, names): | |
44 | assert(offset_in_byte >= 0 and offset_in_byte < 8) | |
45 | self._offset_in_byte = offset_in_byte | |
46 | self._type = type | |
47 | self._names = copy.deepcopy(names) | |
e5aa0be3 PP |
48 | |
49 | @property | |
acfb8213 PP |
50 | def offset_in_byte(self): |
51 | return self._offset_in_byte | |
e5aa0be3 | 52 | |
acfb8213 PP |
53 | @property |
54 | def type(self): | |
55 | return self._type | |
56 | ||
57 | @property | |
58 | def names(self): | |
59 | return self._names | |
e5aa0be3 | 60 | |
e5aa0be3 | 61 | |
acfb8213 PP |
62 | class _AlignSerializationAction(_SerializationAction): |
63 | def __init__(self, offset_in_byte, type, names, value): | |
64 | super().__init__(offset_in_byte, type, names) | |
65 | self._value = value | |
e5aa0be3 | 66 | |
acfb8213 PP |
67 | @property |
68 | def value(self): | |
69 | return self._value | |
e5aa0be3 | 70 | |
e5aa0be3 | 71 | |
acfb8213 PP |
72 | class _SerializeSerializationAction(_SerializationAction): |
73 | def __init__(self, offset_in_byte, type, names): | |
74 | super().__init__(offset_in_byte, type, names) | |
70e191bd | 75 | |
e5aa0be3 | 76 | |
acfb8213 PP |
77 | class _SerializationActions: |
78 | def __init__(self): | |
79 | self.reset() | |
e5aa0be3 | 80 | |
70e191bd | 81 | def reset(self): |
acfb8213 PP |
82 | self._last_alignment = None |
83 | self._last_bit_array_size = None | |
84 | self._actions = [] | |
85 | self._names = [] | |
86 | self._offset_in_byte = 0 | |
87 | ||
88 | def append_root_scope_type(self, t, name): | |
89 | if t is None: | |
90 | return | |
e5aa0be3 | 91 | |
acfb8213 PP |
92 | assert(type(t) is metadata.Struct) |
93 | self._names = [name] | |
94 | self._append_type(t) | |
e5aa0be3 | 95 | |
acfb8213 PP |
96 | @property |
97 | def actions(self): | |
98 | return self._actions | |
99 | ||
100 | def align(self, alignment): | |
101 | do_align = self._must_align(alignment) | |
102 | self._last_alignment = alignment | |
103 | self._last_bit_array_size = alignment | |
104 | self._try_append_align_action(alignment, do_align) | |
105 | ||
106 | def _must_align(self, align_req): | |
107 | return self._last_alignment != align_req or self._last_bit_array_size % align_req != 0 | |
108 | ||
109 | def _append_type(self, t): | |
110 | assert(type(t) in (metadata.Struct, metadata.String, metadata.Integer, | |
111 | metadata.FloatingPoint, metadata.Enum, | |
112 | metadata.Array)) | |
113 | ||
114 | if type(t) in (metadata.String, metadata.Array): | |
115 | assert(type(t) is metadata.String or self._names[-1] == 'uuid') | |
116 | do_align = self._must_align(8) | |
117 | self._last_alignment = 8 | |
118 | self._last_bit_array_size = 8 | |
119 | self._try_append_align_action(8, do_align, t) | |
120 | self._append_serialize_action(t) | |
121 | elif type(t) in (metadata.Integer, metadata.FloatingPoint, | |
122 | metadata.Enum, metadata.Struct): | |
123 | do_align = self._must_align(t.align) | |
124 | self._last_alignment = t.align | |
70e191bd | 125 | |
acfb8213 PP |
126 | if type(t) is metadata.Struct: |
127 | self._last_bit_array_size = t.align | |
128 | else: | |
129 | self._last_bit_array_size = t.size | |
70e191bd | 130 | |
acfb8213 | 131 | self._try_append_align_action(t.align, do_align, t) |
70e191bd PP |
132 | |
133 | if type(t) is metadata.Struct: | |
acfb8213 PP |
134 | for field_name, field_type in t.fields.items(): |
135 | self._names.append(field_name) | |
136 | self._append_type(field_type) | |
137 | del self._names[-1] | |
70e191bd | 138 | else: |
acfb8213 | 139 | self._append_serialize_action(t, t.size) |
70e191bd | 140 | |
acfb8213 PP |
141 | def _try_append_align_action(self, alignment, do_align, t=None): |
142 | offset_in_byte = self._offset_in_byte | |
143 | self._offset_in_byte = _align(self._offset_in_byte, alignment) % 8 | |
70e191bd | 144 | |
acfb8213 PP |
145 | if do_align and alignment > 1: |
146 | self._actions.append(_AlignSerializationAction(offset_in_byte, | |
147 | t, self._names, | |
148 | alignment)) | |
70e191bd | 149 | |
acfb8213 PP |
150 | def _append_serialize_action(self, t, size=None): |
151 | assert(type(t) in (metadata.Integer, metadata.FloatingPoint, | |
152 | metadata.Enum, metadata.String, | |
153 | metadata.Array)) | |
70e191bd | 154 | |
acfb8213 PP |
155 | offset_in_byte = self._offset_in_byte |
156 | ||
157 | if t.size is not None: | |
158 | self._offset_in_byte += t.size | |
159 | self._offset_in_byte %= 8 | |
160 | ||
161 | self._actions.append(_SerializeSerializationAction(offset_in_byte, | |
162 | t, self._names)) | |
70e191bd PP |
163 | |
164 | ||
e5aa0be3 PP |
165 | _PREFIX_TPH = 'tph_' |
166 | _PREFIX_SPC = 'spc_' | |
167 | _PREFIX_SEH = 'seh_' | |
168 | _PREFIX_SEC = 'sec_' | |
169 | _PREFIX_EC = 'ec_' | |
170 | _PREFIX_EP = 'ep_' | |
acfb8213 PP |
171 | _PREFIX_TO_NAME = { |
172 | _PREFIX_TPH: 'trace packet header', | |
173 | _PREFIX_SPC: 'stream packet context', | |
174 | _PREFIX_SEH: 'stream event header', | |
175 | _PREFIX_SEC: 'stream event context', | |
176 | _PREFIX_EC: 'event context', | |
177 | _PREFIX_EP: 'event payload', | |
178 | } | |
e5aa0be3 PP |
179 | |
180 | ||
181 | class CCodeGenerator: | |
182 | def __init__(self, cfg): | |
183 | self._cfg = cfg | |
184 | self._cg = barectf.codegen.CodeGenerator('\t') | |
185 | self._type_to_get_ctype_func = { | |
186 | metadata.Integer: self._get_int_ctype, | |
187 | metadata.FloatingPoint: self._get_float_ctype, | |
188 | metadata.Enum: self._get_enum_ctype, | |
189 | metadata.String: self._get_string_ctype, | |
190 | } | |
191 | self._type_to_generate_serialize_func = { | |
192 | metadata.Integer: self._generate_serialize_int, | |
193 | metadata.FloatingPoint: self._generate_serialize_float, | |
194 | metadata.Enum: self._generate_serialize_enum, | |
195 | metadata.String: self._generate_serialize_string, | |
196 | } | |
acfb8213 | 197 | self._saved_serialization_actions = {} |
e5aa0be3 | 198 | |
27bc6f1e PP |
199 | def _get_stream_clock(self, stream): |
200 | field = None | |
201 | ||
202 | if stream.event_header_type is not None: | |
203 | if 'timestamp' in stream.event_header_type.fields: | |
204 | field = stream.event_header_type['timestamp'] | |
205 | ||
206 | if stream.packet_context_type is not None: | |
207 | if field is None and 'timestamp_begin' in stream.packet_context_type.fields: | |
208 | field = stream.packet_context_type['timestamp_begin'] | |
209 | ||
210 | if field is None and 'timestamp_end' in stream.packet_context_type.fields: | |
211 | field = stream.packet_context_type['timestamp_end'] | |
212 | ||
213 | if field is None: | |
214 | return | |
215 | ||
216 | if field.property_mappings: | |
217 | return field.property_mappings[0].object | |
218 | ||
e5aa0be3 PP |
219 | def _generate_ctx_parent(self): |
220 | tmpl = templates._CTX_PARENT | |
221 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix)) | |
222 | ||
223 | def _generate_ctx(self, stream): | |
224 | tmpl = templates._CTX_BEGIN | |
225 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix, | |
226 | sname=stream.name)) | |
227 | tmpl = 'uint32_t off_tph_{fname};' | |
228 | self._cg.indent() | |
229 | trace_packet_header_type = self._cfg.metadata.trace.packet_header_type | |
230 | ||
231 | if trace_packet_header_type is not None: | |
232 | for field_name in trace_packet_header_type.fields: | |
233 | self._cg.add_lines(tmpl.format(fname=field_name)) | |
234 | ||
235 | tmpl = 'uint32_t off_spc_{fname};' | |
236 | ||
237 | if stream.packet_context_type is not None: | |
238 | for field_name in stream.packet_context_type.fields: | |
239 | self._cg.add_lines(tmpl.format(fname=field_name)) | |
240 | ||
27bc6f1e PP |
241 | clock = self._get_stream_clock(stream) |
242 | ||
243 | if clock is not None: | |
244 | line = '{} cur_last_event_ts;'.format(clock.return_ctype) | |
245 | self._cg.add_line(line) | |
246 | ||
e5aa0be3 PP |
247 | self._cg.unindent() |
248 | tmpl = templates._CTX_END | |
249 | self._cg.add_lines(tmpl) | |
250 | ||
251 | def _generate_ctxs(self): | |
252 | for stream in self._cfg.metadata.streams.values(): | |
253 | self._generate_ctx(stream) | |
254 | ||
255 | def _generate_clock_cb(self, clock): | |
256 | tmpl = templates._CLOCK_CB | |
257 | self._cg.add_lines(tmpl.format(return_ctype=clock.return_ctype, | |
258 | cname=clock.name)) | |
259 | ||
260 | def _generate_clock_cbs(self): | |
261 | for clock in self._cfg.metadata.clocks.values(): | |
262 | self._generate_clock_cb(clock) | |
263 | ||
264 | def _generate_platform_callbacks(self): | |
265 | tmpl = templates._PLATFORM_CALLBACKS_BEGIN | |
266 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix)) | |
267 | self._cg.indent() | |
268 | self._generate_clock_cbs() | |
269 | self._cg.unindent() | |
270 | tmpl = templates._PLATFORM_CALLBACKS_END | |
271 | self._cg.add_lines(tmpl) | |
272 | ||
273 | def generate_bitfield_header(self): | |
274 | self._cg.reset() | |
275 | tmpl = templates._BITFIELD | |
276 | tmpl = tmpl.replace('$prefix$', self._cfg.prefix) | |
277 | tmpl = tmpl.replace('$PREFIX$', self._cfg.prefix.upper()) | |
278 | ||
279 | if self._cfg.metadata.trace.byte_order == metadata.ByteOrder.BE: | |
280 | endian_def = 'BIG_ENDIAN' | |
281 | else: | |
282 | endian_def = 'LITTLE_ENDIAN' | |
283 | ||
284 | tmpl = tmpl.replace('$ENDIAN_DEF$', endian_def) | |
285 | self._cg.add_lines(tmpl) | |
286 | ||
287 | return self._cg.code | |
288 | ||
289 | def _generate_func_init_proto(self): | |
290 | tmpl = templates._FUNC_INIT_PROTO | |
291 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix)) | |
292 | ||
293 | def _get_int_ctype(self, t): | |
294 | signed = 'u' if not t.signed else '' | |
295 | ||
296 | if t.size <= 8: | |
297 | sz = '8' | |
298 | elif t.size <= 16: | |
299 | sz = '16' | |
300 | elif t.size <= 32: | |
301 | sz = '32' | |
302 | elif t.size == 64: | |
303 | sz = '64' | |
304 | ||
305 | return '{}int{}_t'.format(signed, sz) | |
306 | ||
307 | def _get_float_ctype(self, t): | |
308 | if t.exp_size == 8 and t.mant_size == 24 and t.align == 32: | |
309 | ctype = 'float' | |
310 | elif t.exp_size == 11 and t.mant_size == 53 and t.align == 64: | |
311 | ctype = 'double' | |
312 | else: | |
313 | ctype = 'uint64_t' | |
314 | ||
315 | return ctype | |
316 | ||
317 | def _get_enum_ctype(self, t): | |
318 | return self._get_int_ctype(t.value_type) | |
319 | ||
320 | def _get_string_ctype(self, t): | |
321 | return 'const char *' | |
322 | ||
323 | def _get_type_ctype(self, t): | |
324 | return self._type_to_get_ctype_func[type(t)](t) | |
325 | ||
326 | def _generate_type_ctype(self, t): | |
327 | ctype = self._get_type_ctype(t) | |
328 | self._cg.append_to_last_line(ctype) | |
329 | ||
330 | def _generate_proto_param(self, t, name): | |
331 | self._generate_type_ctype(t) | |
332 | self._cg.append_to_last_line(' ') | |
333 | self._cg.append_to_last_line(name) | |
334 | ||
335 | def _generate_proto_params(self, t, name_prefix, exclude_list): | |
336 | self._cg.indent() | |
337 | ||
338 | for field_name, field_type in t.fields.items(): | |
339 | if field_name in exclude_list: | |
340 | continue | |
341 | ||
342 | name = name_prefix + field_name | |
343 | self._cg.append_to_last_line(',') | |
344 | self._cg.add_line('') | |
345 | self._generate_proto_param(field_type, name) | |
346 | ||
347 | self._cg.unindent() | |
348 | ||
349 | def _generate_func_open_proto(self, stream): | |
350 | tmpl = templates._FUNC_OPEN_PROTO_BEGIN | |
351 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix, | |
352 | sname=stream.name)) | |
353 | trace_packet_header_type = self._cfg.metadata.trace.packet_header_type | |
354 | ||
355 | if trace_packet_header_type is not None: | |
356 | exclude_list = ['magic', 'stream_id', 'uuid'] | |
357 | self._generate_proto_params(trace_packet_header_type, _PREFIX_TPH, | |
358 | exclude_list) | |
359 | ||
360 | if stream.packet_context_type is not None: | |
361 | exclude_list = [ | |
362 | 'timestamp_begin', | |
363 | 'timestamp_end', | |
364 | 'packet_size', | |
365 | 'content_size', | |
366 | 'events_discarded', | |
367 | ] | |
368 | self._generate_proto_params(stream.packet_context_type, | |
369 | _PREFIX_SPC, exclude_list) | |
370 | ||
371 | tmpl = templates._FUNC_OPEN_PROTO_END | |
372 | self._cg.add_lines(tmpl) | |
373 | ||
374 | def _generate_func_close_proto(self, stream): | |
375 | tmpl = templates._FUNC_CLOSE_PROTO | |
376 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix, | |
377 | sname=stream.name)) | |
378 | ||
379 | def _generate_func_trace_proto_params(self, stream, event): | |
380 | if stream.event_header_type is not None: | |
381 | exclude_list = [ | |
382 | 'id', | |
383 | 'timestamp', | |
384 | ] | |
385 | self._generate_proto_params(stream.event_header_type, | |
386 | _PREFIX_SEH, exclude_list) | |
387 | ||
388 | if stream.event_context_type is not None: | |
389 | self._generate_proto_params(stream.event_context_type, | |
390 | _PREFIX_SEC, []) | |
391 | ||
392 | if event.context_type is not None: | |
393 | self._generate_proto_params(event.context_type, | |
394 | _PREFIX_EC, []) | |
395 | ||
396 | if event.payload_type is not None: | |
397 | self._generate_proto_params(event.payload_type, | |
398 | _PREFIX_EP, []) | |
399 | ||
400 | def _generate_func_trace_proto(self, stream, event): | |
401 | tmpl = templates._FUNC_TRACE_PROTO_BEGIN | |
402 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix, | |
403 | sname=stream.name, evname=event.name)) | |
404 | self._generate_func_trace_proto_params(stream, event) | |
405 | tmpl = templates._FUNC_TRACE_PROTO_END | |
406 | self._cg.add_lines(tmpl) | |
407 | ||
408 | def _punctuate_proto(self): | |
409 | self._cg.append_to_last_line(';') | |
410 | ||
411 | def generate_header(self): | |
412 | self._cg.reset() | |
413 | dt = datetime.datetime.now().isoformat() | |
414 | bh_filename = self.get_bitfield_header_filename() | |
30c8f734 PP |
415 | prefix_def = '' |
416 | default_stream_def = '' | |
417 | ||
418 | if self._cfg.options.gen_prefix_def: | |
419 | prefix_def = '#define _BARECTF_PREFIX {}'.format(self._cfg.prefix) | |
420 | ||
b4700284 PP |
421 | if self._cfg.options.gen_default_stream_def and self._cfg.metadata.default_stream_name is not None: |
422 | default_stream_def = '#define _BARECTF_DEFAULT_STREAM {}'.format(self._cfg.metadata.default_stream_name) | |
30c8f734 | 423 | |
a50674ee PP |
424 | default_stream_trace_defs = '' |
425 | default_stream_name = self._cfg.metadata.default_stream_name | |
426 | ||
427 | if default_stream_name is not None: | |
428 | default_stream = self._cfg.metadata.streams[default_stream_name] | |
429 | lines = [] | |
430 | ||
431 | for ev_name in default_stream.events.keys(): | |
432 | tmpl = templates._DEFINE_DEFAULT_STREAM_TRACE | |
433 | define = tmpl.format(prefix=self._cfg.prefix, | |
434 | sname=default_stream_name, | |
435 | evname=ev_name) | |
436 | lines.append(define) | |
437 | ||
438 | default_stream_trace_defs = '\n'.join(lines) | |
439 | ||
e5aa0be3 PP |
440 | tmpl = templates._HEADER_BEGIN |
441 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix, | |
442 | ucprefix=self._cfg.prefix.upper(), | |
443 | bitfield_header_filename=bh_filename, | |
30c8f734 PP |
444 | version=barectf.__version__, date=dt, |
445 | prefix_def=prefix_def, | |
a50674ee PP |
446 | default_stream_def=default_stream_def, |
447 | default_stream_trace_defs=default_stream_trace_defs)) | |
e5aa0be3 PP |
448 | self._cg.add_empty_line() |
449 | ||
450 | # platform callbacks structure | |
451 | self._generate_platform_callbacks() | |
452 | self._cg.add_empty_line() | |
453 | ||
454 | # context parent | |
455 | self._generate_ctx_parent() | |
456 | self._cg.add_empty_line() | |
457 | ||
458 | # stream contexts | |
459 | self._generate_ctxs() | |
460 | self._cg.add_empty_line() | |
461 | ||
462 | # initialization function prototype | |
463 | self._generate_func_init_proto() | |
464 | self._punctuate_proto() | |
465 | self._cg.add_empty_line() | |
466 | ||
467 | for stream in self._cfg.metadata.streams.values(): | |
468 | self._generate_func_open_proto(stream) | |
469 | self._punctuate_proto() | |
470 | self._cg.add_empty_line() | |
471 | self._generate_func_close_proto(stream) | |
472 | self._punctuate_proto() | |
473 | self._cg.add_empty_line() | |
474 | ||
475 | for ev in stream.events.values(): | |
476 | self._generate_func_trace_proto(stream, ev) | |
477 | self._punctuate_proto() | |
478 | self._cg.add_empty_line() | |
479 | ||
480 | tmpl = templates._HEADER_END | |
481 | self._cg.add_lines(tmpl.format(ucprefix=self._cfg.prefix.upper())) | |
482 | ||
483 | return self._cg.code | |
484 | ||
485 | def _get_call_event_param_list_from_struct(self, t, prefix, exclude_list): | |
486 | lst = '' | |
487 | ||
488 | for field_name in t.fields: | |
489 | if field_name in exclude_list: | |
490 | continue | |
491 | ||
492 | lst += ', {}{}'.format(prefix, field_name) | |
493 | ||
494 | return lst | |
495 | ||
496 | def _get_call_event_param_list(self, stream, event): | |
497 | lst = '' | |
498 | gcp_func = self._get_call_event_param_list_from_struct | |
499 | ||
500 | if stream.event_header_type is not None: | |
501 | exclude_list = [ | |
502 | 'id', | |
503 | 'timestamp', | |
504 | ] | |
505 | lst += gcp_func(stream.event_header_type, _PREFIX_SEH, exclude_list) | |
506 | ||
507 | if stream.event_context_type is not None: | |
508 | lst += gcp_func(stream.event_context_type, _PREFIX_SEC, []) | |
509 | ||
510 | if event.context_type is not None: | |
511 | lst += gcp_func(event.context_type, _PREFIX_EC, []) | |
512 | ||
513 | if event.payload_type is not None: | |
514 | lst += gcp_func(event.payload_type, _PREFIX_EP, []) | |
515 | ||
516 | return lst | |
517 | ||
518 | def _generate_align(self, at, align): | |
519 | self._cg.add_line('_ALIGN({}, {});'.format(at, align)) | |
e5aa0be3 PP |
520 | |
521 | def _generate_align_type(self, at, t): | |
522 | if t.align == 1: | |
523 | return | |
524 | ||
525 | self._generate_align(at, t.align) | |
526 | ||
527 | def _generate_incr_pos(self, var, value): | |
528 | self._cg.add_line('{} += {};'.format(var, value)) | |
529 | ||
530 | def _generate_incr_pos_bytes(self, var, value): | |
531 | self._generate_incr_pos(var, '_BYTES_TO_BITS({})'.format(value)) | |
532 | ||
533 | def _generate_func_get_event_size_proto(self, stream, event): | |
534 | tmpl = templates._FUNC_GET_EVENT_SIZE_PROTO_BEGIN | |
535 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix, | |
536 | sname=stream.name, evname=event.name)) | |
537 | self._generate_func_trace_proto_params(stream, event) | |
538 | tmpl = templates._FUNC_GET_EVENT_SIZE_PROTO_END | |
539 | self._cg.add_lines(tmpl) | |
540 | ||
e5aa0be3 PP |
541 | def _generate_func_get_event_size(self, stream, event): |
542 | self._generate_func_get_event_size_proto(stream, event) | |
543 | tmpl = templates._FUNC_GET_EVENT_SIZE_BODY_BEGIN | |
f66be07f PP |
544 | lines = tmpl.format(prefix=self._cfg.prefix) |
545 | self._cg.add_lines(lines) | |
e5aa0be3 PP |
546 | self._cg.add_empty_line() |
547 | self._cg.indent() | |
acfb8213 PP |
548 | ser_actions = _SerializationActions() |
549 | ser_actions.append_root_scope_type(stream.event_header_type, | |
550 | _PREFIX_SEH) | |
551 | ser_actions.append_root_scope_type(stream.event_context_type, | |
552 | _PREFIX_SEC) | |
553 | ser_actions.append_root_scope_type(event.context_type, _PREFIX_EC) | |
554 | ser_actions.append_root_scope_type(event.payload_type, _PREFIX_EP) | |
555 | ||
556 | for action in ser_actions.actions: | |
557 | if type(action) is _AlignSerializationAction: | |
558 | if action.names: | |
559 | if len(action.names) == 1: | |
560 | line = 'align {} structure'.format(_PREFIX_TO_NAME[action.names[0]]) | |
561 | else: | |
2277c89f | 562 | fmt = 'align field `{}` ({})' |
acfb8213 PP |
563 | line = fmt.format(action.names[-1], |
564 | _PREFIX_TO_NAME[action.names[0]]) | |
565 | ||
566 | self._cg.add_cc_line(line) | |
567 | ||
568 | self._generate_align('at', action.value) | |
569 | self._cg.add_empty_line() | |
570 | elif type(action) is _SerializeSerializationAction: | |
571 | assert(len(action.names) >= 2) | |
2277c89f | 572 | fmt = 'add size of field `{}` ({})' |
acfb8213 PP |
573 | line = fmt.format(action.names[-1], _PREFIX_TO_NAME[action.names[0]]) |
574 | self._cg.add_cc_line(line) | |
575 | ||
576 | if type(action.type) is metadata.String: | |
577 | param = ''.join(action.names) | |
578 | self._generate_incr_pos_bytes('at', | |
579 | 'strlen({}) + 1'.format(param)) | |
580 | else: | |
581 | self._generate_incr_pos('at', action.type.size) | |
e5aa0be3 | 582 | |
acfb8213 | 583 | self._cg.add_empty_line() |
70e191bd | 584 | |
e5aa0be3 PP |
585 | self._cg.unindent() |
586 | tmpl = templates._FUNC_GET_EVENT_SIZE_BODY_END | |
587 | self._cg.add_lines(tmpl) | |
588 | ||
589 | def _generate_func_serialize_event_proto(self, stream, event): | |
590 | tmpl = templates._FUNC_SERIALIZE_EVENT_PROTO_BEGIN | |
591 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix, | |
592 | sname=stream.name, evname=event.name)) | |
593 | self._generate_func_trace_proto_params(stream, event) | |
594 | tmpl = templates._FUNC_SERIALIZE_EVENT_PROTO_END | |
595 | self._cg.add_lines(tmpl) | |
596 | ||
acfb8213 | 597 | def _generate_bitfield_write(self, ctype, var, ctx, action): |
e5aa0be3 | 598 | ptr = '&{ctx}->buf[_BITS_TO_BYTES({ctx}->at)]'.format(ctx=ctx) |
acfb8213 PP |
599 | start = action.offset_in_byte |
600 | suffix = 'le' if action.type.byte_order is metadata.ByteOrder.LE else 'be' | |
e5aa0be3 | 601 | func = '{}bt_bitfield_write_{}'.format(self._cfg.prefix, suffix) |
193ac49b | 602 | call_fmt = '{func}({ptr}, uint8_t, {start}, {size}, {ctype}, ({ctype}) {var});' |
acfb8213 PP |
603 | call = call_fmt.format(func=func, ptr=ptr, start=start, |
604 | size=action.type.size, ctype=ctype, var=var) | |
e5aa0be3 PP |
605 | self._cg.add_line(call) |
606 | ||
acfb8213 PP |
607 | def _generate_serialize_int(self, var, ctx, action): |
608 | ctype = self._get_int_ctype(action.type) | |
609 | self._generate_bitfield_write(ctype, var, ctx, action) | |
610 | self._generate_incr_pos('{}->at'.format(ctx), action.type.size) | |
e5aa0be3 | 611 | |
acfb8213 PP |
612 | def _generate_serialize_float(self, var, ctx, action): |
613 | ctype = self._get_type_ctype(action.type) | |
7656a395 | 614 | flt_dbl = False |
e5aa0be3 | 615 | |
1405552b | 616 | if ctype == 'float' or ctype == 'double': |
7656a395 | 617 | flt_dbl = True |
1405552b PP |
618 | |
619 | if ctype == 'float': | |
1405552b | 620 | union_name = 'f2u' |
193ac49b | 621 | int_ctype = 'uint32_t' |
1405552b | 622 | elif ctype == 'double': |
1405552b | 623 | union_name = 'd2u' |
193ac49b | 624 | int_ctype = 'uint64_t' |
1405552b | 625 | |
7656a395 PP |
626 | # union for reading the bytes of the floating point number |
627 | self._cg.add_empty_line() | |
628 | self._cg.add_line('{') | |
629 | self._cg.indent() | |
630 | self._cg.add_line('union {name} {name};'.format(name=union_name)) | |
631 | self._cg.add_empty_line() | |
1405552b PP |
632 | self._cg.add_line('{}.f = {};'.format(union_name, var)) |
633 | bf_var = '{}.u'.format(union_name) | |
634 | else: | |
635 | bf_var = '({}) {}'.format(ctype, var) | |
193ac49b | 636 | int_ctype = ctype |
1405552b | 637 | |
acfb8213 | 638 | self._generate_bitfield_write(int_ctype, bf_var, ctx, action) |
7656a395 PP |
639 | |
640 | if flt_dbl: | |
641 | self._cg.unindent() | |
642 | self._cg.add_line('}') | |
643 | self._cg.add_empty_line() | |
644 | ||
acfb8213 | 645 | self._generate_incr_pos('{}->at'.format(ctx), action.type.size) |
e5aa0be3 | 646 | |
acfb8213 PP |
647 | def _generate_serialize_enum(self, var, ctx, action): |
648 | sub_action = _SerializeSerializationAction(action.offset_in_byte, | |
649 | action.type.value_type, | |
650 | action.names) | |
651 | self._generate_serialize_from_action(var, ctx, sub_action) | |
e5aa0be3 | 652 | |
acfb8213 | 653 | def _generate_serialize_string(self, var, ctx, action): |
e5aa0be3 PP |
654 | tmpl = '_write_cstring({}, {});'.format(ctx, var) |
655 | self._cg.add_lines(tmpl) | |
656 | ||
acfb8213 PP |
657 | def _generate_serialize_from_action(self, var, ctx, action): |
658 | func = self._type_to_generate_serialize_func[type(action.type)] | |
659 | func(var, ctx, action) | |
660 | ||
661 | def _generate_serialize_statements_from_actions(self, prefix, action_iter, | |
662 | spec_src=None): | |
663 | for action in action_iter: | |
664 | if type(action) is _AlignSerializationAction: | |
665 | if action.names: | |
666 | if len(action.names) == 1: | |
667 | line = 'align {} structure'.format(_PREFIX_TO_NAME[action.names[0]]) | |
668 | else: | |
2277c89f | 669 | fmt = 'align field `{}` ({})' |
acfb8213 PP |
670 | line = fmt.format(action.names[-1], |
671 | _PREFIX_TO_NAME[action.names[0]]) | |
672 | ||
673 | self._cg.add_cc_line(line) | |
674 | ||
675 | self._generate_align('ctx->at', action.value) | |
676 | self._cg.add_empty_line() | |
677 | elif type(action) is _SerializeSerializationAction: | |
678 | assert(len(action.names) >= 2) | |
2277c89f | 679 | fmt = 'serialize field `{}` ({})' |
acfb8213 PP |
680 | line = fmt.format(action.names[-1], |
681 | _PREFIX_TO_NAME[action.names[0]]) | |
682 | self._cg.add_cc_line(line) | |
683 | field_name = action.names[-1] | |
684 | src = prefix + field_name | |
685 | ||
686 | if spec_src is not None and field_name in spec_src: | |
e5aa0be3 PP |
687 | src = spec_src[field_name] |
688 | ||
acfb8213 PP |
689 | self._generate_serialize_from_action(src, 'ctx', action) |
690 | self._cg.add_empty_line() | |
e5aa0be3 | 691 | |
acfb8213 | 692 | def _generate_func_serialize_event(self, stream, event, orig_ser_actions): |
e5aa0be3 PP |
693 | self._generate_func_serialize_event_proto(stream, event) |
694 | tmpl = templates._FUNC_SERIALIZE_EVENT_BODY_BEGIN | |
f66be07f PP |
695 | lines = tmpl.format(prefix=self._cfg.prefix) |
696 | self._cg.add_lines(lines) | |
e5aa0be3 | 697 | self._cg.indent() |
3cb793a1 | 698 | self._cg.add_empty_line() |
e5aa0be3 PP |
699 | |
700 | if stream.event_header_type is not None: | |
701 | t = stream.event_header_type | |
702 | exclude_list = ['timestamp', 'id'] | |
703 | params = self._get_call_event_param_list_from_struct(t, _PREFIX_SEH, | |
704 | exclude_list) | |
27bc6f1e | 705 | tmpl = '_serialize_stream_event_header_{sname}(ctx, {evid}{params});' |
e5aa0be3 PP |
706 | self._cg.add_cc_line('stream event header') |
707 | self._cg.add_line(tmpl.format(sname=stream.name, evid=event.id, | |
708 | params=params)) | |
709 | self._cg.add_empty_line() | |
710 | ||
711 | if stream.event_context_type is not None: | |
712 | t = stream.event_context_type | |
d04e68e5 PP |
713 | params = self._get_call_event_param_list_from_struct(t, _PREFIX_SEC, |
714 | []) | |
e5aa0be3 PP |
715 | tmpl = '_serialize_stream_event_context_{sname}(ctx{params});' |
716 | self._cg.add_cc_line('stream event context') | |
717 | self._cg.add_line(tmpl.format(sname=stream.name, params=params)) | |
718 | self._cg.add_empty_line() | |
719 | ||
acfb8213 PP |
720 | if event.context_type is not None or event.payload_type is not None: |
721 | ser_actions = copy.deepcopy(orig_ser_actions) | |
722 | ||
e5aa0be3 | 723 | if event.context_type is not None: |
acfb8213 PP |
724 | ser_action_index = len(ser_actions.actions) |
725 | ser_actions.append_root_scope_type(event.context_type, _PREFIX_EC) | |
726 | ser_action_iter = itertools.islice(ser_actions.actions, | |
727 | ser_action_index, None) | |
728 | self._generate_serialize_statements_from_actions(_PREFIX_EC, | |
729 | ser_action_iter) | |
e5aa0be3 PP |
730 | |
731 | if event.payload_type is not None: | |
acfb8213 PP |
732 | ser_action_index = len(ser_actions.actions) |
733 | ser_actions.append_root_scope_type(event.payload_type, _PREFIX_EP) | |
734 | ser_action_iter = itertools.islice(ser_actions.actions, | |
735 | ser_action_index, None) | |
736 | self._generate_serialize_statements_from_actions(_PREFIX_EP, | |
737 | ser_action_iter) | |
e5aa0be3 PP |
738 | |
739 | self._cg.unindent() | |
740 | tmpl = templates._FUNC_SERIALIZE_EVENT_BODY_END | |
741 | self._cg.add_lines(tmpl) | |
742 | ||
743 | def _generate_func_serialize_stream_event_header_proto(self, stream): | |
744 | tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_BEGIN | |
3cb793a1 | 745 | clock_ctype = 'const int' |
e5aa0be3 | 746 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix, |
27bc6f1e | 747 | sname=stream.name)) |
e5aa0be3 PP |
748 | |
749 | if stream.event_header_type is not None: | |
750 | exclude_list = [ | |
751 | 'id', | |
752 | 'timestamp', | |
753 | ] | |
754 | self._generate_proto_params(stream.event_header_type, | |
755 | _PREFIX_SEH, exclude_list) | |
756 | ||
757 | tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_END | |
758 | self._cg.add_lines(tmpl) | |
759 | ||
760 | def _generate_func_serialize_stream_event_context_proto(self, stream): | |
761 | tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_BEGIN | |
762 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix, | |
763 | sname=stream.name)) | |
764 | ||
765 | if stream.event_context_type is not None: | |
766 | self._generate_proto_params(stream.event_context_type, | |
767 | _PREFIX_SEC, []) | |
768 | ||
769 | tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_END | |
770 | self._cg.add_lines(tmpl) | |
771 | ||
acfb8213 PP |
772 | def _generate_func_serialize_stream_event_header(self, stream, |
773 | ser_action_iter): | |
e5aa0be3 PP |
774 | self._generate_func_serialize_stream_event_header_proto(stream) |
775 | tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_BEGIN | |
27bc6f1e | 776 | lines = tmpl.format(prefix=self._cfg.prefix, sname=stream.name) |
f66be07f | 777 | self._cg.add_lines(lines) |
e5aa0be3 | 778 | self._cg.indent() |
27bc6f1e PP |
779 | clock = self._get_stream_clock(stream) |
780 | ||
781 | if clock is not None: | |
782 | tmpl = 'struct {prefix}{sname}_ctx *s_ctx = FROM_VOID_PTR(struct {prefix}{sname}_ctx, vctx);' | |
783 | line = tmpl.format(prefix=self._cfg.prefix, | |
784 | sname=stream.name) | |
785 | self._cg.add_line(line) | |
786 | tmpl = 'const {} ts = s_ctx->cur_last_event_ts;' | |
787 | line = tmpl.format(clock.return_ctype) | |
788 | self._cg.add_line(line) | |
789 | ||
e5aa0be3 | 790 | self._cg.add_empty_line() |
e5aa0be3 PP |
791 | |
792 | if stream.event_header_type is not None: | |
793 | spec_src = {} | |
794 | ||
795 | if 'id' in stream.event_header_type.fields: | |
796 | id_t = stream.event_header_type.fields['id'] | |
797 | id_t_ctype = self._get_int_ctype(id_t) | |
798 | spec_src['id'] = '({}) event_id'.format(id_t_ctype) | |
799 | ||
800 | if 'timestamp' in stream.event_header_type.fields: | |
3cb793a1 PP |
801 | field = stream.event_header_type.fields['timestamp'] |
802 | ts_ctype = self._get_int_ctype(field) | |
e5aa0be3 PP |
803 | spec_src['timestamp'] = '({}) ts'.format(ts_ctype) |
804 | ||
acfb8213 PP |
805 | self._generate_serialize_statements_from_actions(_PREFIX_SEH, |
806 | ser_action_iter, | |
807 | spec_src) | |
e5aa0be3 PP |
808 | |
809 | self._cg.unindent() | |
810 | tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_END | |
811 | self._cg.add_lines(tmpl) | |
812 | ||
acfb8213 PP |
813 | def _generate_func_serialize_stream_event_context(self, stream, |
814 | ser_action_iter): | |
e5aa0be3 PP |
815 | self._generate_func_serialize_stream_event_context_proto(stream) |
816 | tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_BEGIN | |
f66be07f PP |
817 | lines = tmpl.format(prefix=self._cfg.prefix) |
818 | self._cg.add_lines(lines) | |
e5aa0be3 | 819 | self._cg.indent() |
e5aa0be3 PP |
820 | |
821 | if stream.event_context_type is not None: | |
acfb8213 PP |
822 | self._generate_serialize_statements_from_actions(_PREFIX_SEC, |
823 | ser_action_iter) | |
e5aa0be3 PP |
824 | |
825 | self._cg.unindent() | |
826 | tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_END | |
827 | self._cg.add_lines(tmpl) | |
828 | ||
829 | def _generate_func_trace(self, stream, event): | |
830 | self._generate_func_trace_proto(stream, event) | |
831 | params = self._get_call_event_param_list(stream, event) | |
27bc6f1e | 832 | clock = self._get_stream_clock(stream) |
3cb793a1 | 833 | |
27bc6f1e PP |
834 | if clock is not None: |
835 | tmpl = 'ctx->cur_last_event_ts = ctx->parent.cbs.{}_clock_get_value(ctx->parent.data);' | |
836 | save_ts_line = tmpl.format(clock.name) | |
837 | else: | |
838 | save_ts_line = '/* (no clock) */' | |
3cb793a1 | 839 | |
27bc6f1e | 840 | tmpl = templates._FUNC_TRACE_BODY |
e5aa0be3 | 841 | self._cg.add_lines(tmpl.format(sname=stream.name, evname=event.name, |
27bc6f1e | 842 | params=params, save_ts=save_ts_line)) |
e5aa0be3 PP |
843 | |
844 | def _generate_func_init(self): | |
845 | self._generate_func_init_proto() | |
846 | tmpl = templates._FUNC_INIT_BODY | |
847 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix)) | |
848 | ||
849 | def _generate_field_name_cc_line(self, field_name): | |
2277c89f | 850 | self._cg.add_cc_line('`{}` field'.format(field_name)) |
e5aa0be3 | 851 | |
acfb8213 PP |
852 | def _save_serialization_action(self, name, action): |
853 | self._saved_serialization_actions[name] = action | |
1405552b | 854 | |
27bc6f1e PP |
855 | def _get_open_close_ts_line(self, stream): |
856 | clock = self._get_stream_clock(stream) | |
3cb793a1 | 857 | |
27bc6f1e | 858 | if clock is None: |
3cb793a1 PP |
859 | return '' |
860 | ||
27bc6f1e | 861 | tmpl = '\tconst {} ts = ctx->parent.use_cur_last_event_ts ? ctx->cur_last_event_ts : ctx->parent.cbs.{}_clock_get_value(ctx->parent.data);' |
3cb793a1 | 862 | line = tmpl.format(clock.return_ctype, clock.name) |
3cb793a1 PP |
863 | return line |
864 | ||
e5aa0be3 | 865 | def _generate_func_open(self, stream): |
acfb8213 | 866 | def generate_save_offset(name, action): |
e5aa0be3 PP |
867 | tmpl = 'ctx->off_spc_{} = ctx->parent.at;'.format(name) |
868 | self._cg.add_line(tmpl) | |
acfb8213 | 869 | self._save_serialization_action(name, action) |
e5aa0be3 PP |
870 | |
871 | self._generate_func_open_proto(stream) | |
872 | tmpl = templates._FUNC_OPEN_BODY_BEGIN | |
e5aa0be3 | 873 | spc_type = stream.packet_context_type |
27bc6f1e | 874 | ts_line = self._get_open_close_ts_line(stream) |
3cb793a1 PP |
875 | lines = tmpl.format(ts=ts_line) |
876 | self._cg.add_lines(lines) | |
877 | self._cg.indent() | |
e5aa0be3 PP |
878 | self._cg.add_cc_line('do not open a packet that is already open') |
879 | self._cg.add_line('if (ctx->parent.packet_is_open) {') | |
880 | self._cg.indent() | |
3cb793a1 | 881 | self._cg.add_line('ctx->parent.in_tracing_section = saved_in_tracing_section;') |
e5aa0be3 PP |
882 | self._cg.add_line('return;') |
883 | self._cg.unindent() | |
884 | self._cg.add_line('}') | |
885 | self._cg.add_empty_line() | |
886 | self._cg.add_line('ctx->parent.at = 0;') | |
3cb793a1 | 887 | tph_type = self._cfg.metadata.trace.packet_header_type |
acfb8213 | 888 | ser_actions = _SerializationActions() |
e5aa0be3 PP |
889 | |
890 | if tph_type is not None: | |
891 | self._cg.add_empty_line() | |
892 | self._cg.add_cc_line('trace packet header') | |
893 | self._cg.add_line('{') | |
894 | self._cg.indent() | |
acfb8213 | 895 | ser_actions.append_root_scope_type(tph_type, _PREFIX_TPH) |
e5aa0be3 | 896 | |
acfb8213 PP |
897 | for action in ser_actions.actions: |
898 | if type(action) is _AlignSerializationAction: | |
899 | if action.names: | |
900 | if len(action.names) == 1: | |
901 | line = 'align trace packet header structure' | |
902 | else: | |
2277c89f | 903 | line = 'align field `{}`'.format(action.names[-1]) |
e5aa0be3 | 904 | |
acfb8213 | 905 | self._cg.add_cc_line(line) |
e5aa0be3 | 906 | |
acfb8213 PP |
907 | self._generate_align('ctx->parent.at', action.value) |
908 | self._cg.add_empty_line() | |
909 | elif type(action) is _SerializeSerializationAction: | |
910 | assert(len(action.names) >= 2) | |
2277c89f | 911 | fmt = 'serialize field `{}`' |
acfb8213 PP |
912 | line = fmt.format(action.names[-1]) |
913 | self._cg.add_cc_line(line) | |
914 | field_name = action.names[-1] | |
915 | src = _PREFIX_TPH + field_name | |
916 | ||
917 | if field_name == 'magic': | |
918 | src = '0xc1fc1fc1UL' | |
919 | elif field_name == 'stream_id': | |
920 | stream_id_ctype = self._get_int_ctype(action.type) | |
921 | src = '({}) {}'.format(stream_id_ctype, stream.id) | |
922 | elif field_name == 'uuid': | |
923 | self._cg.add_line('{') | |
924 | self._cg.indent() | |
925 | self._cg.add_line('static uint8_t uuid[] = {') | |
926 | self._cg.indent() | |
927 | ||
928 | for b in self._cfg.metadata.trace.uuid.bytes: | |
929 | self._cg.add_line('{},'.format(b)) | |
930 | ||
931 | self._cg.unindent() | |
932 | self._cg.add_line('};') | |
933 | self._cg.add_empty_line() | |
934 | self._generate_align('ctx->parent.at', 8) | |
935 | line = 'memcpy(&ctx->parent.buf[_BITS_TO_BYTES(ctx->parent.at)], uuid, 16);' | |
936 | self._cg.add_line(line) | |
937 | self._generate_incr_pos_bytes('ctx->parent.at', 16) | |
938 | self._cg.unindent() | |
939 | self._cg.add_line('}') | |
940 | self._cg.add_empty_line() | |
941 | continue | |
942 | ||
943 | self._generate_serialize_from_action(src, '(&ctx->parent)', action) | |
944 | self._cg.add_empty_line() | |
e5aa0be3 PP |
945 | |
946 | self._cg.unindent() | |
947 | self._cg.add_lines('}') | |
948 | ||
acfb8213 PP |
949 | spc_action_index = len(ser_actions.actions) |
950 | ||
e5aa0be3 PP |
951 | if spc_type is not None: |
952 | self._cg.add_empty_line() | |
953 | self._cg.add_cc_line('stream packet context') | |
954 | self._cg.add_line('{') | |
955 | self._cg.indent() | |
acfb8213 | 956 | ser_actions.append_root_scope_type(spc_type, _PREFIX_SPC) |
e5aa0be3 PP |
957 | tmpl_off = 'off_spc_{fname}' |
958 | ||
acfb8213 PP |
959 | for action in itertools.islice(ser_actions.actions, spc_action_index, None): |
960 | if type(action) is _AlignSerializationAction: | |
961 | if action.names: | |
962 | if len(action.names) == 1: | |
963 | line = 'align stream packet context structure' | |
964 | else: | |
2277c89f | 965 | line = 'align field `{}`'.format(action.names[-1]) |
e5aa0be3 | 966 | |
acfb8213 PP |
967 | self._cg.add_cc_line(line) |
968 | ||
969 | self._generate_align('ctx->parent.at', action.value) | |
970 | self._cg.add_empty_line() | |
971 | elif type(action) is _SerializeSerializationAction: | |
972 | assert(len(action.names) >= 2) | |
2277c89f | 973 | fmt = 'serialize field `{}`' |
acfb8213 PP |
974 | line = fmt.format(action.names[-1]) |
975 | self._cg.add_cc_line(line) | |
976 | field_name = action.names[-1] | |
977 | src = _PREFIX_SPC + field_name | |
978 | skip_int = False | |
979 | ||
980 | if field_name == 'timestamp_begin': | |
981 | ctype = self._get_type_ctype(action.type) | |
982 | src = '({}) ts'.format(ctype) | |
983 | elif field_name in ['timestamp_end', 'content_size', | |
984 | 'events_discarded']: | |
985 | skip_int = True | |
986 | elif field_name == 'packet_size': | |
987 | ctype = self._get_type_ctype(action.type) | |
988 | src = '({}) ctx->parent.packet_size'.format(ctype) | |
989 | ||
990 | if skip_int: | |
991 | generate_save_offset(field_name, action) | |
992 | self._generate_incr_pos('ctx->parent.at', | |
993 | action.type.size) | |
994 | else: | |
995 | self._generate_serialize_from_action(src, '(&ctx->parent)', | |
996 | action) | |
997 | ||
998 | self._cg.add_empty_line() | |
e5aa0be3 PP |
999 | |
1000 | self._cg.unindent() | |
1001 | self._cg.add_lines('}') | |
1002 | ||
1003 | self._cg.unindent() | |
1004 | tmpl = templates._FUNC_OPEN_BODY_END | |
1005 | self._cg.add_lines(tmpl) | |
1006 | ||
1007 | def _generate_func_close(self, stream): | |
1008 | def generate_goto_offset(name): | |
1009 | tmpl = 'ctx->parent.at = ctx->off_spc_{};'.format(name) | |
1010 | self._cg.add_line(tmpl) | |
1011 | ||
1012 | self._generate_func_close_proto(stream) | |
1013 | tmpl = templates._FUNC_CLOSE_BODY_BEGIN | |
e5aa0be3 | 1014 | spc_type = stream.packet_context_type |
27bc6f1e | 1015 | ts_line = self._get_open_close_ts_line(stream) |
3cb793a1 PP |
1016 | lines = tmpl.format(ts=ts_line) |
1017 | self._cg.add_lines(lines) | |
1018 | self._cg.indent() | |
e5aa0be3 PP |
1019 | self._cg.add_cc_line('do not close a packet that is not open') |
1020 | self._cg.add_line('if (!ctx->parent.packet_is_open) {') | |
1021 | self._cg.indent() | |
3cb793a1 | 1022 | self._cg.add_line('ctx->parent.in_tracing_section = saved_in_tracing_section;') |
e5aa0be3 PP |
1023 | self._cg.add_line('return;') |
1024 | self._cg.unindent() | |
1025 | self._cg.add_line('}') | |
1026 | self._cg.add_empty_line() | |
1027 | self._cg.add_cc_line('save content size') | |
1028 | self._cg.add_line('ctx->parent.content_size = ctx->parent.at;') | |
1029 | ||
1030 | if spc_type is not None: | |
1031 | field_name = 'timestamp_end' | |
1032 | ||
1033 | if field_name in spc_type.fields: | |
1034 | t = spc_type.fields[field_name] | |
1035 | ctype = self._get_type_ctype(t) | |
1036 | src = '({}) ts'.format(ctype) | |
1037 | self._cg.add_empty_line() | |
1038 | self._generate_field_name_cc_line(field_name) | |
1039 | generate_goto_offset(field_name) | |
acfb8213 PP |
1040 | action = self._saved_serialization_actions[field_name] |
1041 | self._generate_serialize_from_action(src, '(&ctx->parent)', action) | |
e5aa0be3 PP |
1042 | |
1043 | field_name = 'content_size' | |
1044 | ||
1045 | if 'content_size' in spc_type.fields: | |
1046 | t = spc_type.fields[field_name] | |
1047 | ctype = self._get_type_ctype(t) | |
1048 | src = '({}) ctx->parent.content_size'.format(ctype) | |
1049 | self._cg.add_empty_line() | |
1050 | self._generate_field_name_cc_line(field_name) | |
1051 | generate_goto_offset(field_name) | |
acfb8213 PP |
1052 | action = self._saved_serialization_actions[field_name] |
1053 | self._generate_serialize_from_action(src, '(&ctx->parent)', action) | |
e5aa0be3 PP |
1054 | |
1055 | field_name = 'events_discarded' | |
1056 | ||
1057 | if field_name in spc_type.fields: | |
1058 | t = spc_type.fields[field_name] | |
1059 | ctype = self._get_type_ctype(t) | |
1060 | src = '({}) ctx->parent.events_discarded'.format(ctype) | |
1061 | self._cg.add_empty_line() | |
1062 | self._generate_field_name_cc_line(field_name) | |
1063 | generate_goto_offset(field_name) | |
acfb8213 PP |
1064 | action = self._saved_serialization_actions[field_name] |
1065 | self._generate_serialize_from_action(src, '(&ctx->parent)', action) | |
e5aa0be3 PP |
1066 | |
1067 | self._cg.unindent() | |
1068 | tmpl = templates._FUNC_CLOSE_BODY_END | |
1069 | self._cg.add_lines(tmpl) | |
e5aa0be3 PP |
1070 | |
1071 | def generate_c_src(self): | |
1072 | self._cg.reset() | |
1073 | dt = datetime.datetime.now().isoformat() | |
1074 | header_filename = self.get_header_filename() | |
1075 | tmpl = templates._C_SRC | |
1076 | self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix, | |
1077 | header_filename=header_filename, | |
1078 | version=barectf.__version__, date=dt)) | |
1079 | self._cg.add_empty_line() | |
1080 | ||
1081 | # initialization function | |
1082 | self._generate_func_init() | |
1083 | self._cg.add_empty_line() | |
1084 | ||
1085 | for stream in self._cfg.metadata.streams.values(): | |
1086 | self._generate_func_open(stream) | |
1087 | self._cg.add_empty_line() | |
1088 | self._generate_func_close(stream) | |
1089 | self._cg.add_empty_line() | |
acfb8213 | 1090 | ser_actions = _SerializationActions() |
e5aa0be3 PP |
1091 | |
1092 | if stream.event_header_type is not None: | |
acfb8213 PP |
1093 | ser_actions.append_root_scope_type(stream.event_header_type, |
1094 | _PREFIX_SEH) | |
1095 | self._generate_func_serialize_stream_event_header(stream, | |
1096 | iter(ser_actions.actions)) | |
e5aa0be3 PP |
1097 | self._cg.add_empty_line() |
1098 | ||
1099 | if stream.event_context_type is not None: | |
acfb8213 PP |
1100 | ser_action_index = len(ser_actions.actions) |
1101 | ser_actions.append_root_scope_type(stream.event_context_type, | |
1102 | _PREFIX_SEC) | |
1103 | ser_action_iter = itertools.islice(ser_actions.actions, | |
1104 | ser_action_index, None) | |
1105 | self._generate_func_serialize_stream_event_context(stream, | |
1106 | ser_action_iter) | |
e5aa0be3 PP |
1107 | self._cg.add_empty_line() |
1108 | ||
1109 | for ev in stream.events.values(): | |
1110 | self._generate_func_get_event_size(stream, ev) | |
1111 | self._cg.add_empty_line() | |
acfb8213 | 1112 | self._generate_func_serialize_event(stream, ev, ser_actions) |
e5aa0be3 PP |
1113 | self._cg.add_empty_line() |
1114 | self._generate_func_trace(stream, ev) | |
1115 | self._cg.add_empty_line() | |
1116 | ||
e5aa0be3 PP |
1117 | return self._cg.code |
1118 | ||
1119 | def get_header_filename(self): | |
1120 | return '{}.h'.format(self._cfg.prefix.rstrip('_')) | |
1121 | ||
1122 | def get_bitfield_header_filename(self): | |
1123 | return '{}-bitfield.h'.format(self._cfg.prefix.rstrip('_')) |