Fix: metadata: add missing return_ctype property
[barectf.git] / barectf / gen.py
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
23 from barectf import templates
24 from barectf import metadata
25 import barectf.codegen
26 import collections
27 import argparse
28 import datetime
29 import barectf
30 import sys
31 import os
32 import re
33
34
35 class _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
89 class 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 = {}
106 self._uf_written = False
107 self._ud_written = False
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):
422 self._reset_per_func_state()
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
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
492
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)
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):
540 self._reset_per_func_state()
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):
609 self._reset_per_func_state()
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):
646 self._reset_per_func_state()
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):
661 self._reset_per_func_state()
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):
669 self._reset_per_func_state()
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
683 def _reset_per_func_state(self):
684 self._uf_written = False
685 self._ud_written = False
686
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
693 self._reset_per_func_state()
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
815 self._reset_per_func_state()
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.053738 seconds and 4 git commands to generate.