barectf: reflow licence headers for 72 columns
[deliverable/barectf.git] / barectf / gen.py
CommitLineData
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
24from barectf import templates
25from barectf import metadata
26import barectf.codegen
27import collections
acfb8213 28import itertools
e5aa0be3
PP
29import argparse
30import datetime
31import barectf
acfb8213 32import copy
e5aa0be3
PP
33import sys
34import os
35import re
36
37
70e191bd
PP
38def _align(v, align):
39 return (v + (align - 1)) & -align
40
41
acfb8213
PP
42class _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
62class _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
72class _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
77class _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
181class 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('_'))
This page took 0.069084 seconds and 4 git commands to generate.