Fix: use unions to write floats to avoid aliasing warnings
[deliverable/barectf.git] / barectf / gen.py
CommitLineData
e5aa0be3
PP
1# The MIT License (MIT)
2#
3# Copyright (c) 2014-2015 Philippe Proulx <pproulx@efficios.com>
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy
6# of this software and associated documentation files (the "Software"), to deal
7# in the Software without restriction, including without limitation the rights
8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9# copies of the Software, and to permit persons to whom the Software is
10# furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in
13# all copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21# THE SOFTWARE.
22
23from barectf import templates
24from barectf import metadata
25import barectf.codegen
26import collections
27import argparse
28import datetime
29import barectf
30import sys
31import os
32import re
33
34
35class _StaticAlignSizeAutomaton:
36 def __init__(self):
37 self._byte_offset = 0
38 self._type_to_update_byte_offset_func = {
39 metadata.Integer: self.write_static_size,
40 metadata.FloatingPoint: self.write_static_size,
41 metadata.Enum: self.write_static_size,
42 metadata.String: self.reset,
43 }
44
45 @property
46 def byte_offset(self):
47 return self._byte_offset
48
49 @byte_offset.setter
50 def byte_offset(self, value):
51 self._byte_offset = value
52
53 def _wrap_byte_offset(self):
54 self._byte_offset %= 8
55
56 def align(self, align):
57 # align byte offset
58 self._byte_offset = (self._byte_offset + (align - 1)) & -align
59
60 # wrap on current byte
61 self._wrap_byte_offset()
62
63 def write_type(self, t):
64 self._type_to_update_byte_offset_func[type(t)](t)
65
66 def write_static_size(self, t):
67 # increment byte offset
68 self._byte_offset += t.size
69
70 # wrap on current byte
71 self._wrap_byte_offset()
72
73 def reset(self, t=None):
74 # reset byte offset (strings are always byte-aligned)
75 self._byte_offset = 0
76
77 def set_unknown(self):
78 self._byte_offset = None
79
80
81_PREFIX_TPH = 'tph_'
82_PREFIX_SPC = 'spc_'
83_PREFIX_SEH = 'seh_'
84_PREFIX_SEC = 'sec_'
85_PREFIX_EC = 'ec_'
86_PREFIX_EP = 'ep_'
87
88
89class CCodeGenerator:
90 def __init__(self, cfg):
91 self._cfg = cfg
92 self._cg = barectf.codegen.CodeGenerator('\t')
93 self._type_to_get_ctype_func = {
94 metadata.Integer: self._get_int_ctype,
95 metadata.FloatingPoint: self._get_float_ctype,
96 metadata.Enum: self._get_enum_ctype,
97 metadata.String: self._get_string_ctype,
98 }
99 self._type_to_generate_serialize_func = {
100 metadata.Integer: self._generate_serialize_int,
101 metadata.FloatingPoint: self._generate_serialize_float,
102 metadata.Enum: self._generate_serialize_enum,
103 metadata.String: self._generate_serialize_string,
104 }
105 self._saved_byte_offsets = {}
1405552b
PP
106 self._uf_written = False
107 self._ud_written = False
e5aa0be3
PP
108 self._sasa = _StaticAlignSizeAutomaton()
109
110 def _generate_ctx_parent(self):
111 tmpl = templates._CTX_PARENT
112 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix))
113
114 def _generate_ctx(self, stream):
115 tmpl = templates._CTX_BEGIN
116 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
117 sname=stream.name))
118 tmpl = 'uint32_t off_tph_{fname};'
119 self._cg.indent()
120 trace_packet_header_type = self._cfg.metadata.trace.packet_header_type
121
122 if trace_packet_header_type is not None:
123 for field_name in trace_packet_header_type.fields:
124 self._cg.add_lines(tmpl.format(fname=field_name))
125
126 tmpl = 'uint32_t off_spc_{fname};'
127
128 if stream.packet_context_type is not None:
129 for field_name in stream.packet_context_type.fields:
130 self._cg.add_lines(tmpl.format(fname=field_name))
131
132 self._cg.unindent()
133 tmpl = templates._CTX_END
134 self._cg.add_lines(tmpl)
135
136 def _generate_ctxs(self):
137 for stream in self._cfg.metadata.streams.values():
138 self._generate_ctx(stream)
139
140 def _generate_clock_cb(self, clock):
141 tmpl = templates._CLOCK_CB
142 self._cg.add_lines(tmpl.format(return_ctype=clock.return_ctype,
143 cname=clock.name))
144
145 def _generate_clock_cbs(self):
146 for clock in self._cfg.metadata.clocks.values():
147 self._generate_clock_cb(clock)
148
149 def _generate_platform_callbacks(self):
150 tmpl = templates._PLATFORM_CALLBACKS_BEGIN
151 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix))
152 self._cg.indent()
153 self._generate_clock_cbs()
154 self._cg.unindent()
155 tmpl = templates._PLATFORM_CALLBACKS_END
156 self._cg.add_lines(tmpl)
157
158 def generate_bitfield_header(self):
159 self._cg.reset()
160 tmpl = templates._BITFIELD
161 tmpl = tmpl.replace('$prefix$', self._cfg.prefix)
162 tmpl = tmpl.replace('$PREFIX$', self._cfg.prefix.upper())
163
164 if self._cfg.metadata.trace.byte_order == metadata.ByteOrder.BE:
165 endian_def = 'BIG_ENDIAN'
166 else:
167 endian_def = 'LITTLE_ENDIAN'
168
169 tmpl = tmpl.replace('$ENDIAN_DEF$', endian_def)
170 self._cg.add_lines(tmpl)
171
172 return self._cg.code
173
174 def _generate_func_init_proto(self):
175 tmpl = templates._FUNC_INIT_PROTO
176 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix))
177
178 def _get_int_ctype(self, t):
179 signed = 'u' if not t.signed else ''
180
181 if t.size <= 8:
182 sz = '8'
183 elif t.size <= 16:
184 sz = '16'
185 elif t.size <= 32:
186 sz = '32'
187 elif t.size == 64:
188 sz = '64'
189
190 return '{}int{}_t'.format(signed, sz)
191
192 def _get_float_ctype(self, t):
193 if t.exp_size == 8 and t.mant_size == 24 and t.align == 32:
194 ctype = 'float'
195 elif t.exp_size == 11 and t.mant_size == 53 and t.align == 64:
196 ctype = 'double'
197 else:
198 ctype = 'uint64_t'
199
200 return ctype
201
202 def _get_enum_ctype(self, t):
203 return self._get_int_ctype(t.value_type)
204
205 def _get_string_ctype(self, t):
206 return 'const char *'
207
208 def _get_type_ctype(self, t):
209 return self._type_to_get_ctype_func[type(t)](t)
210
211 def _generate_type_ctype(self, t):
212 ctype = self._get_type_ctype(t)
213 self._cg.append_to_last_line(ctype)
214
215 def _generate_proto_param(self, t, name):
216 self._generate_type_ctype(t)
217 self._cg.append_to_last_line(' ')
218 self._cg.append_to_last_line(name)
219
220 def _generate_proto_params(self, t, name_prefix, exclude_list):
221 self._cg.indent()
222
223 for field_name, field_type in t.fields.items():
224 if field_name in exclude_list:
225 continue
226
227 name = name_prefix + field_name
228 self._cg.append_to_last_line(',')
229 self._cg.add_line('')
230 self._generate_proto_param(field_type, name)
231
232 self._cg.unindent()
233
234 def _generate_func_open_proto(self, stream):
235 tmpl = templates._FUNC_OPEN_PROTO_BEGIN
236 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
237 sname=stream.name))
238 trace_packet_header_type = self._cfg.metadata.trace.packet_header_type
239
240 if trace_packet_header_type is not None:
241 exclude_list = ['magic', 'stream_id', 'uuid']
242 self._generate_proto_params(trace_packet_header_type, _PREFIX_TPH,
243 exclude_list)
244
245 if stream.packet_context_type is not None:
246 exclude_list = [
247 'timestamp_begin',
248 'timestamp_end',
249 'packet_size',
250 'content_size',
251 'events_discarded',
252 ]
253 self._generate_proto_params(stream.packet_context_type,
254 _PREFIX_SPC, exclude_list)
255
256 tmpl = templates._FUNC_OPEN_PROTO_END
257 self._cg.add_lines(tmpl)
258
259 def _generate_func_close_proto(self, stream):
260 tmpl = templates._FUNC_CLOSE_PROTO
261 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
262 sname=stream.name))
263
264 def _generate_func_trace_proto_params(self, stream, event):
265 if stream.event_header_type is not None:
266 exclude_list = [
267 'id',
268 'timestamp',
269 ]
270 self._generate_proto_params(stream.event_header_type,
271 _PREFIX_SEH, exclude_list)
272
273 if stream.event_context_type is not None:
274 self._generate_proto_params(stream.event_context_type,
275 _PREFIX_SEC, [])
276
277 if event.context_type is not None:
278 self._generate_proto_params(event.context_type,
279 _PREFIX_EC, [])
280
281 if event.payload_type is not None:
282 self._generate_proto_params(event.payload_type,
283 _PREFIX_EP, [])
284
285 def _generate_func_trace_proto(self, stream, event):
286 tmpl = templates._FUNC_TRACE_PROTO_BEGIN
287 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
288 sname=stream.name, evname=event.name))
289 self._generate_func_trace_proto_params(stream, event)
290 tmpl = templates._FUNC_TRACE_PROTO_END
291 self._cg.add_lines(tmpl)
292
293 def _punctuate_proto(self):
294 self._cg.append_to_last_line(';')
295
296 def generate_header(self):
297 self._cg.reset()
298 dt = datetime.datetime.now().isoformat()
299 bh_filename = self.get_bitfield_header_filename()
300 tmpl = templates._HEADER_BEGIN
301 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
302 ucprefix=self._cfg.prefix.upper(),
303 bitfield_header_filename=bh_filename,
304 version=barectf.__version__, date=dt))
305 self._cg.add_empty_line()
306
307 # platform callbacks structure
308 self._generate_platform_callbacks()
309 self._cg.add_empty_line()
310
311 # context parent
312 self._generate_ctx_parent()
313 self._cg.add_empty_line()
314
315 # stream contexts
316 self._generate_ctxs()
317 self._cg.add_empty_line()
318
319 # initialization function prototype
320 self._generate_func_init_proto()
321 self._punctuate_proto()
322 self._cg.add_empty_line()
323
324 for stream in self._cfg.metadata.streams.values():
325 self._generate_func_open_proto(stream)
326 self._punctuate_proto()
327 self._cg.add_empty_line()
328 self._generate_func_close_proto(stream)
329 self._punctuate_proto()
330 self._cg.add_empty_line()
331
332 for ev in stream.events.values():
333 self._generate_func_trace_proto(stream, ev)
334 self._punctuate_proto()
335 self._cg.add_empty_line()
336
337 tmpl = templates._HEADER_END
338 self._cg.add_lines(tmpl.format(ucprefix=self._cfg.prefix.upper()))
339
340 return self._cg.code
341
342 def _get_call_event_param_list_from_struct(self, t, prefix, exclude_list):
343 lst = ''
344
345 for field_name in t.fields:
346 if field_name in exclude_list:
347 continue
348
349 lst += ', {}{}'.format(prefix, field_name)
350
351 return lst
352
353 def _get_call_event_param_list(self, stream, event):
354 lst = ''
355 gcp_func = self._get_call_event_param_list_from_struct
356
357 if stream.event_header_type is not None:
358 exclude_list = [
359 'id',
360 'timestamp',
361 ]
362 lst += gcp_func(stream.event_header_type, _PREFIX_SEH, exclude_list)
363
364 if stream.event_context_type is not None:
365 lst += gcp_func(stream.event_context_type, _PREFIX_SEC, [])
366
367 if event.context_type is not None:
368 lst += gcp_func(event.context_type, _PREFIX_EC, [])
369
370 if event.payload_type is not None:
371 lst += gcp_func(event.payload_type, _PREFIX_EP, [])
372
373 return lst
374
375 def _generate_align(self, at, align):
376 self._cg.add_line('_ALIGN({}, {});'.format(at, align))
377 self._sasa.align(align)
378
379 def _generate_align_type(self, at, t):
380 if t.align == 1:
381 return
382
383 self._generate_align(at, t.align)
384
385 def _generate_incr_pos(self, var, value):
386 self._cg.add_line('{} += {};'.format(var, value))
387
388 def _generate_incr_pos_bytes(self, var, value):
389 self._generate_incr_pos(var, '_BYTES_TO_BITS({})'.format(value))
390
391 def _generate_func_get_event_size_proto(self, stream, event):
392 tmpl = templates._FUNC_GET_EVENT_SIZE_PROTO_BEGIN
393 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
394 sname=stream.name, evname=event.name))
395 self._generate_func_trace_proto_params(stream, event)
396 tmpl = templates._FUNC_GET_EVENT_SIZE_PROTO_END
397 self._cg.add_lines(tmpl)
398
399 def _generate_func_get_event_size_from_entity(self, prefix, t):
400 self._cg.add_line('{')
401 self._cg.indent()
402 self._cg.add_cc_line('align structure')
403 self._generate_align_type('at', t)
404
405 for field_name, field_type in t.fields.items():
406 self._cg.add_empty_line()
407 self._generate_field_name_cc_line(field_name)
408 self._generate_align_type('at', field_type)
409
410 if type(field_type) is metadata.String:
411 param = prefix + field_name
412 self._generate_incr_pos_bytes('at',
413 'strlen({}) + 1'.format(param))
414 else:
415 self._generate_incr_pos('at', field_type.size)
416
417 self._cg.unindent()
418 self._cg.add_line('}')
419 self._cg.add_empty_line()
420
421 def _generate_func_get_event_size(self, stream, event):
1405552b 422 self._reset_per_func_state()
e5aa0be3
PP
423 self._generate_func_get_event_size_proto(stream, event)
424 tmpl = templates._FUNC_GET_EVENT_SIZE_BODY_BEGIN
425 self._cg.add_lines(tmpl)
426 self._cg.add_empty_line()
427 self._cg.indent()
428 func = self._generate_func_get_event_size_from_entity
429
430 if stream.event_header_type is not None:
431 self._cg.add_cc_line('stream event header')
432 func(_PREFIX_SEH, stream.event_header_type)
433
434 if stream.event_context_type is not None:
435 self._cg.add_cc_line('stream event context')
436 func(_PREFIX_SEC, stream.event_context_type)
437
438 if event.context_type is not None:
439 self._cg.add_cc_line('event context')
440 func(_PREFIX_EC, event.context_type)
441
442 if event.payload_type is not None:
443 self._cg.add_cc_line('event payload')
444 func(_PREFIX_EP, event.payload_type)
445
446 self._cg.unindent()
447 tmpl = templates._FUNC_GET_EVENT_SIZE_BODY_END
448 self._cg.add_lines(tmpl)
449
450 def _generate_func_serialize_event_proto(self, stream, event):
451 tmpl = templates._FUNC_SERIALIZE_EVENT_PROTO_BEGIN
452 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
453 sname=stream.name, evname=event.name))
454 self._generate_func_trace_proto_params(stream, event)
455 tmpl = templates._FUNC_SERIALIZE_EVENT_PROTO_END
456 self._cg.add_lines(tmpl)
457
458 def _generate_bitfield_write(self, var, ctx, t):
459 ptr = '&{ctx}->buf[_BITS_TO_BYTES({ctx}->at)]'.format(ctx=ctx)
460 start = self._sasa.byte_offset
461 suffix = 'le' if t.byte_order is metadata.ByteOrder.LE else 'be'
462 func = '{}bt_bitfield_write_{}'.format(self._cfg.prefix, suffix)
463 call = '{}({}, uint8_t, {}, {}, {});'.format(func, ptr, start, t.size,
464 var)
465 self._cg.add_line(call)
466
467 def _generate_serialize_int(self, var, ctx, t):
468 self._generate_bitfield_write(var, ctx, t)
469 self._generate_incr_pos('{}->at'.format(ctx), t.size)
470
471 def _generate_serialize_float(self, var, ctx, t):
472 ctype = self._get_type_ctype(t)
473
1405552b
PP
474 if ctype == 'float' or ctype == 'double':
475 gen_union_var = False
476
477 if ctype == 'float':
478 if not self._uf_written:
479 self._uf_written = True
480 gen_union_var = True
481
482 union_name = 'f2u'
483 elif ctype == 'double':
484 if not self._ud_written:
485 self._ud_written = True
486 gen_union_var = True
487
488 union_name = 'd2u'
489
490 if gen_union_var:
491 # union for reading the bytes of the floating point number
e5aa0be3 492
1405552b
PP
493 self._cg.add_line('union {name} {name};'.format(name=union_name))
494 self._cg.add_empty_line()
495
496 self._cg.add_line('{}.f = {};'.format(union_name, var))
497 bf_var = '{}.u'.format(union_name)
498 else:
499 bf_var = '({}) {}'.format(ctype, var)
500
501 self._generate_bitfield_write(bf_var, ctx, t)
e5aa0be3
PP
502 self._generate_incr_pos('{}->at'.format(ctx), t.size)
503
504 def _generate_serialize_enum(self, var, ctx, t):
505 self._generate_serialize_type(var, ctx, t.value_type)
506
507 def _generate_serialize_string(self, var, ctx, t):
508 tmpl = '_write_cstring({}, {});'.format(ctx, var)
509 self._cg.add_lines(tmpl)
510
511 def _generate_serialize_type(self, var, ctx, t):
512 self._type_to_generate_serialize_func[type(t)](var, ctx, t)
513 self._sasa.write_type(t)
514
515 def _generate_func_serialize_event_from_entity(self, prefix, t,
516 spec_src=None):
517 self._cg.add_line('{')
518 self._cg.indent()
519 self._cg.add_cc_line('align structure')
520 self._sasa.reset()
521 self._generate_align_type('ctx->at', t)
522
523 for field_name, field_type in t.fields.items():
524 src = prefix + field_name
525
526 if spec_src is not None:
527 if field_name in spec_src:
528 src = spec_src[field_name]
529
530 self._cg.add_empty_line()
531 self._generate_field_name_cc_line(field_name)
532 self._generate_align_type('ctx->at', field_type)
533 self._generate_serialize_type(src, 'ctx', field_type)
534
535 self._cg.unindent()
536 self._cg.add_line('}')
537 self._cg.add_empty_line()
538
539 def _generate_func_serialize_event(self, stream, event):
1405552b 540 self._reset_per_func_state()
e5aa0be3
PP
541 self._generate_func_serialize_event_proto(stream, event)
542 tmpl = templates._FUNC_SERIALIZE_EVENT_BODY_BEGIN
543 self._cg.add_lines(tmpl)
544 self._cg.indent()
545
546 if stream.event_header_type is not None:
547 t = stream.event_header_type
548 exclude_list = ['timestamp', 'id']
549 params = self._get_call_event_param_list_from_struct(t, _PREFIX_SEH,
550 exclude_list)
551 tmpl = '_serialize_stream_event_header_{sname}(ctx, {evid}{params});'
552 self._cg.add_cc_line('stream event header')
553 self._cg.add_line(tmpl.format(sname=stream.name, evid=event.id,
554 params=params))
555 self._cg.add_empty_line()
556
557 if stream.event_context_type is not None:
558 t = stream.event_context_type
559 params = self._get_call_event_param_list_from_struct(t, _PREFIX_SEH,
560 exclude_list)
561 tmpl = '_serialize_stream_event_context_{sname}(ctx{params});'
562 self._cg.add_cc_line('stream event context')
563 self._cg.add_line(tmpl.format(sname=stream.name, params=params))
564 self._cg.add_empty_line()
565
566 if event.context_type is not None:
567 self._cg.add_cc_line('event context')
568 self._generate_func_serialize_event_from_entity(_PREFIX_EC,
569 event.context_type)
570
571 if event.payload_type is not None:
572 self._cg.add_cc_line('event payload')
573 self._generate_func_serialize_event_from_entity(_PREFIX_EP,
574 event.payload_type)
575
576 self._cg.unindent()
577 tmpl = templates._FUNC_SERIALIZE_EVENT_BODY_END
578 self._cg.add_lines(tmpl)
579
580 def _generate_func_serialize_stream_event_header_proto(self, stream):
581 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_BEGIN
582 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
583 sname=stream.name))
584
585 if stream.event_header_type is not None:
586 exclude_list = [
587 'id',
588 'timestamp',
589 ]
590 self._generate_proto_params(stream.event_header_type,
591 _PREFIX_SEH, exclude_list)
592
593 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_END
594 self._cg.add_lines(tmpl)
595
596 def _generate_func_serialize_stream_event_context_proto(self, stream):
597 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_BEGIN
598 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
599 sname=stream.name))
600
601 if stream.event_context_type is not None:
602 self._generate_proto_params(stream.event_context_type,
603 _PREFIX_SEC, [])
604
605 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_END
606 self._cg.add_lines(tmpl)
607
608 def _generate_func_serialize_stream_event_header(self, stream):
1405552b 609 self._reset_per_func_state()
e5aa0be3
PP
610 self._generate_func_serialize_stream_event_header_proto(stream)
611 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_BEGIN
612 self._cg.add_lines(tmpl)
613 self._cg.indent()
614
615 if stream.event_header_type is not None:
616 if 'timestamp' in stream.event_header_type.fields:
617 timestamp = stream.event_header_type.fields['timestamp']
618 ts_ctype = self._get_int_ctype(timestamp)
619 clock = timestamp.property_mappings[0].object
620 clock_name = clock.name
621 clock_ctype = clock.return_ctype
622 tmpl = '{} ts = ctx->cbs.{}_clock_get_value(ctx->data);'
623 self._cg.add_line(tmpl.format(clock_ctype, clock_name))
624
625 self._cg.add_empty_line()
626 func = self._generate_func_serialize_event_from_entity
627
628 if stream.event_header_type is not None:
629 spec_src = {}
630
631 if 'id' in stream.event_header_type.fields:
632 id_t = stream.event_header_type.fields['id']
633 id_t_ctype = self._get_int_ctype(id_t)
634 spec_src['id'] = '({}) event_id'.format(id_t_ctype)
635
636 if 'timestamp' in stream.event_header_type.fields:
637 spec_src['timestamp'] = '({}) ts'.format(ts_ctype)
638
639 func(_PREFIX_SEH, stream.event_header_type, spec_src)
640
641 self._cg.unindent()
642 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_END
643 self._cg.add_lines(tmpl)
644
645 def _generate_func_serialize_stream_event_context(self, stream):
1405552b 646 self._reset_per_func_state()
e5aa0be3
PP
647 self._generate_func_serialize_stream_event_context_proto(stream)
648 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_BEGIN
649 self._cg.add_lines(tmpl)
650 self._cg.indent()
651 func = self._generate_func_serialize_event_from_entity
652
653 if stream.event_context_type is not None:
654 func(_PREFIX_SEC, stream.event_context_type)
655
656 self._cg.unindent()
657 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_END
658 self._cg.add_lines(tmpl)
659
660 def _generate_func_trace(self, stream, event):
1405552b 661 self._reset_per_func_state()
e5aa0be3
PP
662 self._generate_func_trace_proto(stream, event)
663 params = self._get_call_event_param_list(stream, event)
664 tmpl = templates._FUNC_TRACE_BODY
665 self._cg.add_lines(tmpl.format(sname=stream.name, evname=event.name,
666 params=params))
667
668 def _generate_func_init(self):
1405552b 669 self._reset_per_func_state()
e5aa0be3
PP
670 self._generate_func_init_proto()
671 tmpl = templates._FUNC_INIT_BODY
672 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix))
673
674 def _generate_field_name_cc_line(self, field_name):
675 self._cg.add_cc_line('"{}" field'.format(field_name))
676
677 def _save_byte_offset(self, name):
678 self._saved_byte_offsets[name] = self._sasa.byte_offset
679
680 def _restore_byte_offset(self, name):
681 self._sasa.byte_offset = self._saved_byte_offsets[name]
682
1405552b
PP
683 def _reset_per_func_state(self):
684 self._uf_written = False
685 self._ud_written = False
686
e5aa0be3
PP
687 def _generate_func_open(self, stream):
688 def generate_save_offset(name):
689 tmpl = 'ctx->off_spc_{} = ctx->parent.at;'.format(name)
690 self._cg.add_line(tmpl)
691 self._save_byte_offset(name)
692
1405552b 693 self._reset_per_func_state()
e5aa0be3
PP
694 self._generate_func_open_proto(stream)
695 tmpl = templates._FUNC_OPEN_BODY_BEGIN
696 self._cg.add_lines(tmpl)
697 self._cg.indent()
698 tph_type = self._cfg.metadata.trace.packet_header_type
699 spc_type = stream.packet_context_type
700
701 if spc_type is not None and 'timestamp_begin' in spc_type.fields:
702 field = spc_type.fields['timestamp_begin']
703 tmpl = '{} ts = ctx->parent.cbs.{}_clock_get_value(ctx->parent.data);'
704 clock = field.property_mappings[0].object
705 clock_ctype = clock.return_ctype
706 clock_name = clock.name
707 self._cg.add_line(tmpl.format(clock_ctype, clock_name))
708 self._cg.add_empty_line()
709
710 self._cg.add_cc_line('do not open a packet that is already open')
711 self._cg.add_line('if (ctx->parent.packet_is_open) {')
712 self._cg.indent()
713 self._cg.add_line('return;')
714 self._cg.unindent()
715 self._cg.add_line('}')
716 self._cg.add_empty_line()
717 self._cg.add_line('ctx->parent.at = 0;')
718
719 if tph_type is not None:
720 self._cg.add_empty_line()
721 self._cg.add_cc_line('trace packet header')
722 self._cg.add_line('{')
723 self._cg.indent()
724 self._cg.add_cc_line('align structure')
725 self._sasa.reset()
726 self._generate_align_type('ctx->parent.at', tph_type)
727
728 for field_name, field_type in tph_type.fields.items():
729 src = _PREFIX_TPH + field_name
730
731 if field_name == 'magic':
732 src = '0xc1fc1fc1UL'
733 elif field_name == 'stream_id':
734 stream_id_ctype = self._get_int_ctype(field_type)
735 src = '({}) {}'.format(stream_id_ctype, stream.id)
736 elif field_name == 'uuid':
737 self._cg.add_empty_line()
738 self._generate_field_name_cc_line(field_name)
739 self._cg.add_line('{')
740 self._cg.indent()
741 self._cg.add_line('static uint8_t uuid[] = {')
742 self._cg.indent()
743
744 for b in self._cfg.metadata.trace.uuid.bytes:
745 self._cg.add_line('{},'.format(b))
746
747 self._cg.unindent()
748 self._cg.add_line('};')
749 self._cg.add_empty_line()
750 self._generate_align('ctx->parent.at', 8)
751 line = 'memcpy(&ctx->parent.buf[_BITS_TO_BYTES(ctx->parent.at)], uuid, 16);'
752 self._cg.add_line(line)
753 self._generate_incr_pos_bytes('ctx->parent.at', 16)
754 self._cg.unindent()
755 self._cg.add_line('}')
756 self._sasa.reset()
757 continue
758
759 self._cg.add_empty_line()
760 self._generate_field_name_cc_line(field_name)
761 self._generate_align_type('ctx->parent.at', field_type)
762 self._generate_serialize_type(src, '(&ctx->parent)', field_type)
763
764 self._cg.unindent()
765 self._cg.add_lines('}')
766
767 if spc_type is not None:
768 self._cg.add_empty_line()
769 self._cg.add_cc_line('stream packet context')
770 self._cg.add_line('{')
771 self._cg.indent()
772 self._cg.add_cc_line('align structure')
773 self._sasa.reset()
774 self._generate_align_type('ctx->parent.at', spc_type)
775 tmpl_off = 'off_spc_{fname}'
776
777 for field_name, field_type in spc_type.fields.items():
778 src = _PREFIX_SPC + field_name
779 skip_int = False
780 self._cg.add_empty_line()
781 self._generate_field_name_cc_line(field_name)
782
783 if field_name == 'timestamp_begin':
784 ctype = self._get_type_ctype(field_type)
785 src = '({}) ts'.format(ctype)
786 elif field_name in ['timestamp_end', 'content_size',
787 'events_discarded']:
788 skip_int = True
789 elif field_name == 'packet_size':
790 ctype = self._get_type_ctype(field_type)
791 src = '({}) ctx->parent.packet_size'.format(ctype)
792
793 self._generate_align_type('ctx->parent.at', field_type)
794
795 if skip_int:
796 generate_save_offset(field_name)
797 self._generate_incr_pos('ctx->parent.at', field_type.size)
798 self._sasa.write_type(field_type)
799 else:
800 self._generate_serialize_type(src, '(&ctx->parent)',
801 field_type)
802
803 self._cg.unindent()
804 self._cg.add_lines('}')
805
806 self._cg.unindent()
807 tmpl = templates._FUNC_OPEN_BODY_END
808 self._cg.add_lines(tmpl)
809
810 def _generate_func_close(self, stream):
811 def generate_goto_offset(name):
812 tmpl = 'ctx->parent.at = ctx->off_spc_{};'.format(name)
813 self._cg.add_line(tmpl)
814
1405552b 815 self._reset_per_func_state()
e5aa0be3
PP
816 self._generate_func_close_proto(stream)
817 tmpl = templates._FUNC_CLOSE_BODY_BEGIN
818 self._cg.add_lines(tmpl)
819 self._cg.indent()
820 spc_type = stream.packet_context_type
821
822 if spc_type is not None:
823 if 'timestamp_end' in spc_type.fields:
824 tmpl = '{} ts = ctx->parent.cbs.{}_clock_get_value(ctx->parent.data);'
825 field = spc_type.fields['timestamp_end']
826 clock = field.property_mappings[0].object
827 clock_ctype = clock.return_ctype
828 clock_name = clock.name
829 self._cg.add_line(tmpl.format(clock_ctype, clock_name))
830 self._cg.add_empty_line()
831
832 self._cg.add_cc_line('do not close a packet that is not open')
833 self._cg.add_line('if (!ctx->parent.packet_is_open) {')
834 self._cg.indent()
835 self._cg.add_line('return;')
836 self._cg.unindent()
837 self._cg.add_line('}')
838 self._cg.add_empty_line()
839 self._cg.add_cc_line('save content size')
840 self._cg.add_line('ctx->parent.content_size = ctx->parent.at;')
841
842 if spc_type is not None:
843 field_name = 'timestamp_end'
844
845 if field_name in spc_type.fields:
846 t = spc_type.fields[field_name]
847 ctype = self._get_type_ctype(t)
848 src = '({}) ts'.format(ctype)
849 self._cg.add_empty_line()
850 self._generate_field_name_cc_line(field_name)
851 generate_goto_offset(field_name)
852 self._restore_byte_offset(field_name)
853 self._generate_serialize_type(src, '(&ctx->parent)', t)
854
855 field_name = 'content_size'
856
857 if 'content_size' in spc_type.fields:
858 t = spc_type.fields[field_name]
859 ctype = self._get_type_ctype(t)
860 src = '({}) ctx->parent.content_size'.format(ctype)
861 self._cg.add_empty_line()
862 self._generate_field_name_cc_line(field_name)
863 generate_goto_offset(field_name)
864 self._restore_byte_offset(field_name)
865 self._generate_serialize_type(src, '(&ctx->parent)', t)
866
867 field_name = 'events_discarded'
868
869 if field_name in spc_type.fields:
870 t = spc_type.fields[field_name]
871 ctype = self._get_type_ctype(t)
872 src = '({}) ctx->parent.events_discarded'.format(ctype)
873 self._cg.add_empty_line()
874 self._generate_field_name_cc_line(field_name)
875 generate_goto_offset(field_name)
876 self._restore_byte_offset(field_name)
877 self._generate_serialize_type(src, '(&ctx->parent)', t)
878
879 self._cg.unindent()
880 tmpl = templates._FUNC_CLOSE_BODY_END
881 self._cg.add_lines(tmpl)
882 self._sasa.reset()
883
884 def generate_c_src(self):
885 self._cg.reset()
886 dt = datetime.datetime.now().isoformat()
887 header_filename = self.get_header_filename()
888 tmpl = templates._C_SRC
889 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
890 header_filename=header_filename,
891 version=barectf.__version__, date=dt))
892 self._cg.add_empty_line()
893
894 # initialization function
895 self._generate_func_init()
896 self._cg.add_empty_line()
897
898 for stream in self._cfg.metadata.streams.values():
899 self._generate_func_open(stream)
900 self._cg.add_empty_line()
901 self._generate_func_close(stream)
902 self._cg.add_empty_line()
903
904 if stream.event_header_type is not None:
905 self._generate_func_serialize_stream_event_header(stream)
906 self._cg.add_empty_line()
907
908 if stream.event_context_type is not None:
909 self._generate_func_serialize_stream_event_context(stream)
910 self._cg.add_empty_line()
911
912 for ev in stream.events.values():
913 self._generate_func_get_event_size(stream, ev)
914 self._cg.add_empty_line()
915 self._generate_func_serialize_event(stream, ev)
916 self._cg.add_empty_line()
917 self._generate_func_trace(stream, ev)
918 self._cg.add_empty_line()
919
920
921 return self._cg.code
922
923 def get_header_filename(self):
924 return '{}.h'.format(self._cfg.prefix.rstrip('_'))
925
926 def get_bitfield_header_filename(self):
927 return '{}-bitfield.h'.format(self._cfg.prefix.rstrip('_'))
This page took 0.072046 seconds and 4 git commands to generate.