Fixing the missing initialization of the field 'initialized' in the global context...
[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 = {}
106 self._sasa = _StaticAlignSizeAutomaton()
107
108 def _generate_ctx_parent(self):
109 tmpl = templates._CTX_PARENT
110 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix))
111
112 def _generate_ctx(self, stream):
113 tmpl = templates._CTX_BEGIN
114 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
115 sname=stream.name))
116 tmpl = 'uint32_t off_tph_{fname};'
117 self._cg.indent()
118 trace_packet_header_type = self._cfg.metadata.trace.packet_header_type
119
120 if trace_packet_header_type is not None:
121 for field_name in trace_packet_header_type.fields:
122 self._cg.add_lines(tmpl.format(fname=field_name))
123
124 tmpl = 'uint32_t off_spc_{fname};'
125
126 if stream.packet_context_type is not None:
127 for field_name in stream.packet_context_type.fields:
128 self._cg.add_lines(tmpl.format(fname=field_name))
129
130 self._cg.unindent()
131 tmpl = templates._CTX_END
132 self._cg.add_lines(tmpl)
133
134 def _generate_ctxs(self):
135 for stream in self._cfg.metadata.streams.values():
136 self._generate_ctx(stream)
137
138 def _generate_clock_cb(self, clock):
139 tmpl = templates._CLOCK_CB
140 self._cg.add_lines(tmpl.format(return_ctype=clock.return_ctype,
141 cname=clock.name))
142
143 def _generate_clock_cbs(self):
144 for clock in self._cfg.metadata.clocks.values():
145 self._generate_clock_cb(clock)
146
147 def _generate_platform_callbacks(self):
148 tmpl = templates._PLATFORM_CALLBACKS_BEGIN
149 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix))
150 self._cg.indent()
151 self._generate_clock_cbs()
152 self._cg.unindent()
153 tmpl = templates._PLATFORM_CALLBACKS_END
154 self._cg.add_lines(tmpl)
155
156 def generate_bitfield_header(self):
157 self._cg.reset()
158 tmpl = templates._BITFIELD
159 tmpl = tmpl.replace('$prefix$', self._cfg.prefix)
160 tmpl = tmpl.replace('$PREFIX$', self._cfg.prefix.upper())
161
162 if self._cfg.metadata.trace.byte_order == metadata.ByteOrder.BE:
163 endian_def = 'BIG_ENDIAN'
164 else:
165 endian_def = 'LITTLE_ENDIAN'
166
167 tmpl = tmpl.replace('$ENDIAN_DEF$', endian_def)
168 self._cg.add_lines(tmpl)
169
170 return self._cg.code
171
172 def _generate_func_init_proto(self):
173 tmpl = templates._FUNC_INIT_PROTO
174 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix))
175
176 def _get_int_ctype(self, t):
177 signed = 'u' if not t.signed else ''
178
179 if t.size <= 8:
180 sz = '8'
181 elif t.size <= 16:
182 sz = '16'
183 elif t.size <= 32:
184 sz = '32'
185 elif t.size == 64:
186 sz = '64'
187
188 return '{}int{}_t'.format(signed, sz)
189
190 def _get_float_ctype(self, t):
191 if t.exp_size == 8 and t.mant_size == 24 and t.align == 32:
192 ctype = 'float'
193 elif t.exp_size == 11 and t.mant_size == 53 and t.align == 64:
194 ctype = 'double'
195 else:
196 ctype = 'uint64_t'
197
198 return ctype
199
200 def _get_enum_ctype(self, t):
201 return self._get_int_ctype(t.value_type)
202
203 def _get_string_ctype(self, t):
204 return 'const char *'
205
206 def _get_type_ctype(self, t):
207 return self._type_to_get_ctype_func[type(t)](t)
208
209 def _generate_type_ctype(self, t):
210 ctype = self._get_type_ctype(t)
211 self._cg.append_to_last_line(ctype)
212
213 def _generate_proto_param(self, t, name):
214 self._generate_type_ctype(t)
215 self._cg.append_to_last_line(' ')
216 self._cg.append_to_last_line(name)
217
218 def _generate_proto_params(self, t, name_prefix, exclude_list):
219 self._cg.indent()
220
221 for field_name, field_type in t.fields.items():
222 if field_name in exclude_list:
223 continue
224
225 name = name_prefix + field_name
226 self._cg.append_to_last_line(',')
227 self._cg.add_line('')
228 self._generate_proto_param(field_type, name)
229
230 self._cg.unindent()
231
232 def _generate_func_open_proto(self, stream):
233 tmpl = templates._FUNC_OPEN_PROTO_BEGIN
234 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
235 sname=stream.name))
236 trace_packet_header_type = self._cfg.metadata.trace.packet_header_type
237
238 if trace_packet_header_type is not None:
239 exclude_list = ['magic', 'stream_id', 'uuid']
240 self._generate_proto_params(trace_packet_header_type, _PREFIX_TPH,
241 exclude_list)
242
243 if stream.packet_context_type is not None:
244 exclude_list = [
245 'timestamp_begin',
246 'timestamp_end',
247 'packet_size',
248 'content_size',
249 'events_discarded',
250 ]
251 self._generate_proto_params(stream.packet_context_type,
252 _PREFIX_SPC, exclude_list)
253
254 tmpl = templates._FUNC_OPEN_PROTO_END
255 self._cg.add_lines(tmpl)
256
257 def _generate_func_close_proto(self, stream):
258 tmpl = templates._FUNC_CLOSE_PROTO
259 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
260 sname=stream.name))
261
262 def _generate_func_trace_proto_params(self, stream, event):
263 if stream.event_header_type is not None:
264 exclude_list = [
265 'id',
266 'timestamp',
267 ]
268 self._generate_proto_params(stream.event_header_type,
269 _PREFIX_SEH, exclude_list)
270
271 if stream.event_context_type is not None:
272 self._generate_proto_params(stream.event_context_type,
273 _PREFIX_SEC, [])
274
275 if event.context_type is not None:
276 self._generate_proto_params(event.context_type,
277 _PREFIX_EC, [])
278
279 if event.payload_type is not None:
280 self._generate_proto_params(event.payload_type,
281 _PREFIX_EP, [])
282
283 def _generate_func_trace_proto(self, stream, event):
284 tmpl = templates._FUNC_TRACE_PROTO_BEGIN
285 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
286 sname=stream.name, evname=event.name))
287 self._generate_func_trace_proto_params(stream, event)
288 tmpl = templates._FUNC_TRACE_PROTO_END
289 self._cg.add_lines(tmpl)
290
291 def _punctuate_proto(self):
292 self._cg.append_to_last_line(';')
293
294 def generate_header(self):
295 self._cg.reset()
296 dt = datetime.datetime.now().isoformat()
297 bh_filename = self.get_bitfield_header_filename()
298 tmpl = templates._HEADER_BEGIN
299 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
300 ucprefix=self._cfg.prefix.upper(),
301 bitfield_header_filename=bh_filename,
302 version=barectf.__version__, date=dt))
303 self._cg.add_empty_line()
304
305 # platform callbacks structure
306 self._generate_platform_callbacks()
307 self._cg.add_empty_line()
308
309 # context parent
310 self._generate_ctx_parent()
311 self._cg.add_empty_line()
312
313 # stream contexts
314 self._generate_ctxs()
315 self._cg.add_empty_line()
316
317 # initialization function prototype
318 self._generate_func_init_proto()
319 self._punctuate_proto()
320 self._cg.add_empty_line()
321
322 for stream in self._cfg.metadata.streams.values():
323 self._generate_func_open_proto(stream)
324 self._punctuate_proto()
325 self._cg.add_empty_line()
326 self._generate_func_close_proto(stream)
327 self._punctuate_proto()
328 self._cg.add_empty_line()
329
330 for ev in stream.events.values():
331 self._generate_func_trace_proto(stream, ev)
332 self._punctuate_proto()
333 self._cg.add_empty_line()
334
335 tmpl = templates._HEADER_END
336 self._cg.add_lines(tmpl.format(ucprefix=self._cfg.prefix.upper()))
337
338 return self._cg.code
339
340 def _get_call_event_param_list_from_struct(self, t, prefix, exclude_list):
341 lst = ''
342
343 for field_name in t.fields:
344 if field_name in exclude_list:
345 continue
346
347 lst += ', {}{}'.format(prefix, field_name)
348
349 return lst
350
351 def _get_call_event_param_list(self, stream, event):
352 lst = ''
353 gcp_func = self._get_call_event_param_list_from_struct
354
355 if stream.event_header_type is not None:
356 exclude_list = [
357 'id',
358 'timestamp',
359 ]
360 lst += gcp_func(stream.event_header_type, _PREFIX_SEH, exclude_list)
361
362 if stream.event_context_type is not None:
363 lst += gcp_func(stream.event_context_type, _PREFIX_SEC, [])
364
365 if event.context_type is not None:
366 lst += gcp_func(event.context_type, _PREFIX_EC, [])
367
368 if event.payload_type is not None:
369 lst += gcp_func(event.payload_type, _PREFIX_EP, [])
370
371 return lst
372
373 def _generate_align(self, at, align):
374 self._cg.add_line('_ALIGN({}, {});'.format(at, align))
375 self._sasa.align(align)
376
377 def _generate_align_type(self, at, t):
378 if t.align == 1:
379 return
380
381 self._generate_align(at, t.align)
382
383 def _generate_incr_pos(self, var, value):
384 self._cg.add_line('{} += {};'.format(var, value))
385
386 def _generate_incr_pos_bytes(self, var, value):
387 self._generate_incr_pos(var, '_BYTES_TO_BITS({})'.format(value))
388
389 def _generate_func_get_event_size_proto(self, stream, event):
390 tmpl = templates._FUNC_GET_EVENT_SIZE_PROTO_BEGIN
391 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
392 sname=stream.name, evname=event.name))
393 self._generate_func_trace_proto_params(stream, event)
394 tmpl = templates._FUNC_GET_EVENT_SIZE_PROTO_END
395 self._cg.add_lines(tmpl)
396
397 def _generate_func_get_event_size_from_entity(self, prefix, t):
398 self._cg.add_line('{')
399 self._cg.indent()
400 self._cg.add_cc_line('align structure')
401 self._generate_align_type('at', t)
402
403 for field_name, field_type in t.fields.items():
404 self._cg.add_empty_line()
405 self._generate_field_name_cc_line(field_name)
406 self._generate_align_type('at', field_type)
407
408 if type(field_type) is metadata.String:
409 param = prefix + field_name
410 self._generate_incr_pos_bytes('at',
411 'strlen({}) + 1'.format(param))
412 else:
413 self._generate_incr_pos('at', field_type.size)
414
415 self._cg.unindent()
416 self._cg.add_line('}')
417 self._cg.add_empty_line()
418
419 def _generate_func_get_event_size(self, stream, event):
420 self._generate_func_get_event_size_proto(stream, event)
421 tmpl = templates._FUNC_GET_EVENT_SIZE_BODY_BEGIN
422 self._cg.add_lines(tmpl)
423 self._cg.add_empty_line()
424 self._cg.indent()
425 func = self._generate_func_get_event_size_from_entity
426
427 if stream.event_header_type is not None:
428 self._cg.add_cc_line('stream event header')
429 func(_PREFIX_SEH, stream.event_header_type)
430
431 if stream.event_context_type is not None:
432 self._cg.add_cc_line('stream event context')
433 func(_PREFIX_SEC, stream.event_context_type)
434
435 if event.context_type is not None:
436 self._cg.add_cc_line('event context')
437 func(_PREFIX_EC, event.context_type)
438
439 if event.payload_type is not None:
440 self._cg.add_cc_line('event payload')
441 func(_PREFIX_EP, event.payload_type)
442
443 self._cg.unindent()
444 tmpl = templates._FUNC_GET_EVENT_SIZE_BODY_END
445 self._cg.add_lines(tmpl)
446
447 def _generate_func_serialize_event_proto(self, stream, event):
448 tmpl = templates._FUNC_SERIALIZE_EVENT_PROTO_BEGIN
449 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
450 sname=stream.name, evname=event.name))
451 self._generate_func_trace_proto_params(stream, event)
452 tmpl = templates._FUNC_SERIALIZE_EVENT_PROTO_END
453 self._cg.add_lines(tmpl)
454
455 def _generate_bitfield_write(self, var, ctx, t):
456 ptr = '&{ctx}->buf[_BITS_TO_BYTES({ctx}->at)]'.format(ctx=ctx)
457 start = self._sasa.byte_offset
458 suffix = 'le' if t.byte_order is metadata.ByteOrder.LE else 'be'
459 func = '{}bt_bitfield_write_{}'.format(self._cfg.prefix, suffix)
460 call = '{}({}, uint8_t, {}, {}, {});'.format(func, ptr, start, t.size,
461 var)
462 self._cg.add_line(call)
463
464 def _generate_serialize_int(self, var, ctx, t):
465 self._generate_bitfield_write(var, ctx, t)
466 self._generate_incr_pos('{}->at'.format(ctx), t.size)
467
468 def _generate_serialize_float(self, var, ctx, t):
469 ctype = self._get_type_ctype(t)
470
471 if ctype == 'float':
472 ctype = 'uint32_t'
473 elif ctype == 'double':
474 ctype = 'uint64_t'
475
476 var_casted = '*(({}*) &{})'.format(ctype, var)
477 self._generate_bitfield_write(var_casted, ctx, t)
478 self._generate_incr_pos('{}->at'.format(ctx), t.size)
479
480 def _generate_serialize_enum(self, var, ctx, t):
481 self._generate_serialize_type(var, ctx, t.value_type)
482
483 def _generate_serialize_string(self, var, ctx, t):
484 tmpl = '_write_cstring({}, {});'.format(ctx, var)
485 self._cg.add_lines(tmpl)
486
487 def _generate_serialize_type(self, var, ctx, t):
488 self._type_to_generate_serialize_func[type(t)](var, ctx, t)
489 self._sasa.write_type(t)
490
491 def _generate_func_serialize_event_from_entity(self, prefix, t,
492 spec_src=None):
493 self._cg.add_line('{')
494 self._cg.indent()
495 self._cg.add_cc_line('align structure')
496 self._sasa.reset()
497 self._generate_align_type('ctx->at', t)
498
499 for field_name, field_type in t.fields.items():
500 src = prefix + field_name
501
502 if spec_src is not None:
503 if field_name in spec_src:
504 src = spec_src[field_name]
505
506 self._cg.add_empty_line()
507 self._generate_field_name_cc_line(field_name)
508 self._generate_align_type('ctx->at', field_type)
509 self._generate_serialize_type(src, 'ctx', field_type)
510
511 self._cg.unindent()
512 self._cg.add_line('}')
513 self._cg.add_empty_line()
514
515 def _generate_func_serialize_event(self, stream, event):
516 self._generate_func_serialize_event_proto(stream, event)
517 tmpl = templates._FUNC_SERIALIZE_EVENT_BODY_BEGIN
518 self._cg.add_lines(tmpl)
519 self._cg.indent()
520
521 if stream.event_header_type is not None:
522 t = stream.event_header_type
523 exclude_list = ['timestamp', 'id']
524 params = self._get_call_event_param_list_from_struct(t, _PREFIX_SEH,
525 exclude_list)
526 tmpl = '_serialize_stream_event_header_{sname}(ctx, {evid}{params});'
527 self._cg.add_cc_line('stream event header')
528 self._cg.add_line(tmpl.format(sname=stream.name, evid=event.id,
529 params=params))
530 self._cg.add_empty_line()
531
532 if stream.event_context_type is not None:
533 t = stream.event_context_type
534 params = self._get_call_event_param_list_from_struct(t, _PREFIX_SEH,
535 exclude_list)
536 tmpl = '_serialize_stream_event_context_{sname}(ctx{params});'
537 self._cg.add_cc_line('stream event context')
538 self._cg.add_line(tmpl.format(sname=stream.name, params=params))
539 self._cg.add_empty_line()
540
541 if event.context_type is not None:
542 self._cg.add_cc_line('event context')
543 self._generate_func_serialize_event_from_entity(_PREFIX_EC,
544 event.context_type)
545
546 if event.payload_type is not None:
547 self._cg.add_cc_line('event payload')
548 self._generate_func_serialize_event_from_entity(_PREFIX_EP,
549 event.payload_type)
550
551 self._cg.unindent()
552 tmpl = templates._FUNC_SERIALIZE_EVENT_BODY_END
553 self._cg.add_lines(tmpl)
554
555 def _generate_func_serialize_stream_event_header_proto(self, stream):
556 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_BEGIN
557 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
558 sname=stream.name))
559
560 if stream.event_header_type is not None:
561 exclude_list = [
562 'id',
563 'timestamp',
564 ]
565 self._generate_proto_params(stream.event_header_type,
566 _PREFIX_SEH, exclude_list)
567
568 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_END
569 self._cg.add_lines(tmpl)
570
571 def _generate_func_serialize_stream_event_context_proto(self, stream):
572 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_BEGIN
573 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
574 sname=stream.name))
575
576 if stream.event_context_type is not None:
577 self._generate_proto_params(stream.event_context_type,
578 _PREFIX_SEC, [])
579
580 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_END
581 self._cg.add_lines(tmpl)
582
583 def _generate_func_serialize_stream_event_header(self, stream):
584 self._generate_func_serialize_stream_event_header_proto(stream)
585 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_BEGIN
586 self._cg.add_lines(tmpl)
587 self._cg.indent()
588
589 if stream.event_header_type is not None:
590 if 'timestamp' in stream.event_header_type.fields:
591 timestamp = stream.event_header_type.fields['timestamp']
592 ts_ctype = self._get_int_ctype(timestamp)
593 clock = timestamp.property_mappings[0].object
594 clock_name = clock.name
595 clock_ctype = clock.return_ctype
596 tmpl = '{} ts = ctx->cbs.{}_clock_get_value(ctx->data);'
597 self._cg.add_line(tmpl.format(clock_ctype, clock_name))
598
599 self._cg.add_empty_line()
600 func = self._generate_func_serialize_event_from_entity
601
602 if stream.event_header_type is not None:
603 spec_src = {}
604
605 if 'id' in stream.event_header_type.fields:
606 id_t = stream.event_header_type.fields['id']
607 id_t_ctype = self._get_int_ctype(id_t)
608 spec_src['id'] = '({}) event_id'.format(id_t_ctype)
609
610 if 'timestamp' in stream.event_header_type.fields:
611 spec_src['timestamp'] = '({}) ts'.format(ts_ctype)
612
613 func(_PREFIX_SEH, stream.event_header_type, spec_src)
614
615 self._cg.unindent()
616 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_END
617 self._cg.add_lines(tmpl)
618
619 def _generate_func_serialize_stream_event_context(self, stream):
620 self._generate_func_serialize_stream_event_context_proto(stream)
621 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_BEGIN
622 self._cg.add_lines(tmpl)
623 self._cg.indent()
624 func = self._generate_func_serialize_event_from_entity
625
626 if stream.event_context_type is not None:
627 func(_PREFIX_SEC, stream.event_context_type)
628
629 self._cg.unindent()
630 tmpl = templates._FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_END
631 self._cg.add_lines(tmpl)
632
633 def _generate_func_trace(self, stream, event):
634 self._generate_func_trace_proto(stream, event)
635 params = self._get_call_event_param_list(stream, event)
636 tmpl = templates._FUNC_TRACE_BODY
637 self._cg.add_lines(tmpl.format(sname=stream.name, evname=event.name,
638 params=params))
639
640 def _generate_func_init(self):
641 self._generate_func_init_proto()
642 tmpl = templates._FUNC_INIT_BODY
643 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix))
644
645 def _generate_field_name_cc_line(self, field_name):
646 self._cg.add_cc_line('"{}" field'.format(field_name))
647
648 def _save_byte_offset(self, name):
649 self._saved_byte_offsets[name] = self._sasa.byte_offset
650
651 def _restore_byte_offset(self, name):
652 self._sasa.byte_offset = self._saved_byte_offsets[name]
653
654 def _generate_func_open(self, stream):
655 def generate_save_offset(name):
656 tmpl = 'ctx->off_spc_{} = ctx->parent.at;'.format(name)
657 self._cg.add_line(tmpl)
658 self._save_byte_offset(name)
659
660 self._generate_func_open_proto(stream)
661 tmpl = templates._FUNC_OPEN_BODY_BEGIN
662 self._cg.add_lines(tmpl)
663 self._cg.indent()
664 tph_type = self._cfg.metadata.trace.packet_header_type
665 spc_type = stream.packet_context_type
666
667 if spc_type is not None and 'timestamp_begin' in spc_type.fields:
668 field = spc_type.fields['timestamp_begin']
669 tmpl = '{} ts = ctx->parent.cbs.{}_clock_get_value(ctx->parent.data);'
670 clock = field.property_mappings[0].object
671 clock_ctype = clock.return_ctype
672 clock_name = clock.name
673 self._cg.add_line(tmpl.format(clock_ctype, clock_name))
674 self._cg.add_empty_line()
675
676 self._cg.add_cc_line('do not open a packet that is already open')
677 self._cg.add_line('if (ctx->parent.packet_is_open) {')
678 self._cg.indent()
679 self._cg.add_line('return;')
680 self._cg.unindent()
681 self._cg.add_line('}')
682 self._cg.add_empty_line()
683 self._cg.add_line('ctx->parent.at = 0;')
684
685 if tph_type is not None:
686 self._cg.add_empty_line()
687 self._cg.add_cc_line('trace packet header')
688 self._cg.add_line('{')
689 self._cg.indent()
690 self._cg.add_cc_line('align structure')
691 self._sasa.reset()
692 self._generate_align_type('ctx->parent.at', tph_type)
693
694 for field_name, field_type in tph_type.fields.items():
695 src = _PREFIX_TPH + field_name
696
697 if field_name == 'magic':
698 src = '0xc1fc1fc1UL'
699 elif field_name == 'stream_id':
700 stream_id_ctype = self._get_int_ctype(field_type)
701 src = '({}) {}'.format(stream_id_ctype, stream.id)
702 elif field_name == 'uuid':
703 self._cg.add_empty_line()
704 self._generate_field_name_cc_line(field_name)
705 self._cg.add_line('{')
706 self._cg.indent()
707 self._cg.add_line('static uint8_t uuid[] = {')
708 self._cg.indent()
709
710 for b in self._cfg.metadata.trace.uuid.bytes:
711 self._cg.add_line('{},'.format(b))
712
713 self._cg.unindent()
714 self._cg.add_line('};')
715 self._cg.add_empty_line()
716 self._generate_align('ctx->parent.at', 8)
717 line = 'memcpy(&ctx->parent.buf[_BITS_TO_BYTES(ctx->parent.at)], uuid, 16);'
718 self._cg.add_line(line)
719 self._generate_incr_pos_bytes('ctx->parent.at', 16)
720 self._cg.unindent()
721 self._cg.add_line('}')
722 self._sasa.reset()
723 continue
724
725 self._cg.add_empty_line()
726 self._generate_field_name_cc_line(field_name)
727 self._generate_align_type('ctx->parent.at', field_type)
728 self._generate_serialize_type(src, '(&ctx->parent)', field_type)
729
730 self._cg.unindent()
731 self._cg.add_lines('}')
732
733 if spc_type is not None:
734 self._cg.add_empty_line()
735 self._cg.add_cc_line('stream packet context')
736 self._cg.add_line('{')
737 self._cg.indent()
738 self._cg.add_cc_line('align structure')
739 self._sasa.reset()
740 self._generate_align_type('ctx->parent.at', spc_type)
741 tmpl_off = 'off_spc_{fname}'
742
743 for field_name, field_type in spc_type.fields.items():
744 src = _PREFIX_SPC + field_name
745 skip_int = False
746 self._cg.add_empty_line()
747 self._generate_field_name_cc_line(field_name)
748
749 if field_name == 'timestamp_begin':
750 ctype = self._get_type_ctype(field_type)
751 src = '({}) ts'.format(ctype)
752 elif field_name in ['timestamp_end', 'content_size',
753 'events_discarded']:
754 skip_int = True
755 elif field_name == 'packet_size':
756 ctype = self._get_type_ctype(field_type)
757 src = '({}) ctx->parent.packet_size'.format(ctype)
758
759 self._generate_align_type('ctx->parent.at', field_type)
760
761 if skip_int:
762 generate_save_offset(field_name)
763 self._generate_incr_pos('ctx->parent.at', field_type.size)
764 self._sasa.write_type(field_type)
765 else:
766 self._generate_serialize_type(src, '(&ctx->parent)',
767 field_type)
768
769 self._cg.unindent()
770 self._cg.add_lines('}')
771
772 self._cg.unindent()
773 tmpl = templates._FUNC_OPEN_BODY_END
774 self._cg.add_lines(tmpl)
775
776 def _generate_func_close(self, stream):
777 def generate_goto_offset(name):
778 tmpl = 'ctx->parent.at = ctx->off_spc_{};'.format(name)
779 self._cg.add_line(tmpl)
780
781 self._generate_func_close_proto(stream)
782 tmpl = templates._FUNC_CLOSE_BODY_BEGIN
783 self._cg.add_lines(tmpl)
784 self._cg.indent()
785 spc_type = stream.packet_context_type
786
787 if spc_type is not None:
788 if 'timestamp_end' in spc_type.fields:
789 tmpl = '{} ts = ctx->parent.cbs.{}_clock_get_value(ctx->parent.data);'
790 field = spc_type.fields['timestamp_end']
791 clock = field.property_mappings[0].object
792 clock_ctype = clock.return_ctype
793 clock_name = clock.name
794 self._cg.add_line(tmpl.format(clock_ctype, clock_name))
795 self._cg.add_empty_line()
796
797 self._cg.add_cc_line('do not close a packet that is not open')
798 self._cg.add_line('if (!ctx->parent.packet_is_open) {')
799 self._cg.indent()
800 self._cg.add_line('return;')
801 self._cg.unindent()
802 self._cg.add_line('}')
803 self._cg.add_empty_line()
804 self._cg.add_cc_line('save content size')
805 self._cg.add_line('ctx->parent.content_size = ctx->parent.at;')
806
807 if spc_type is not None:
808 field_name = 'timestamp_end'
809
810 if field_name in spc_type.fields:
811 t = spc_type.fields[field_name]
812 ctype = self._get_type_ctype(t)
813 src = '({}) ts'.format(ctype)
814 self._cg.add_empty_line()
815 self._generate_field_name_cc_line(field_name)
816 generate_goto_offset(field_name)
817 self._restore_byte_offset(field_name)
818 self._generate_serialize_type(src, '(&ctx->parent)', t)
819
820 field_name = 'content_size'
821
822 if 'content_size' in spc_type.fields:
823 t = spc_type.fields[field_name]
824 ctype = self._get_type_ctype(t)
825 src = '({}) ctx->parent.content_size'.format(ctype)
826 self._cg.add_empty_line()
827 self._generate_field_name_cc_line(field_name)
828 generate_goto_offset(field_name)
829 self._restore_byte_offset(field_name)
830 self._generate_serialize_type(src, '(&ctx->parent)', t)
831
832 field_name = 'events_discarded'
833
834 if field_name in spc_type.fields:
835 t = spc_type.fields[field_name]
836 ctype = self._get_type_ctype(t)
837 src = '({}) ctx->parent.events_discarded'.format(ctype)
838 self._cg.add_empty_line()
839 self._generate_field_name_cc_line(field_name)
840 generate_goto_offset(field_name)
841 self._restore_byte_offset(field_name)
842 self._generate_serialize_type(src, '(&ctx->parent)', t)
843
844 self._cg.unindent()
845 tmpl = templates._FUNC_CLOSE_BODY_END
846 self._cg.add_lines(tmpl)
847 self._sasa.reset()
848
849 def generate_c_src(self):
850 self._cg.reset()
851 dt = datetime.datetime.now().isoformat()
852 header_filename = self.get_header_filename()
853 tmpl = templates._C_SRC
854 self._cg.add_lines(tmpl.format(prefix=self._cfg.prefix,
855 header_filename=header_filename,
856 version=barectf.__version__, date=dt))
857 self._cg.add_empty_line()
858
859 # initialization function
860 self._generate_func_init()
861 self._cg.add_empty_line()
862
863 for stream in self._cfg.metadata.streams.values():
864 self._generate_func_open(stream)
865 self._cg.add_empty_line()
866 self._generate_func_close(stream)
867 self._cg.add_empty_line()
868
869 if stream.event_header_type is not None:
870 self._generate_func_serialize_stream_event_header(stream)
871 self._cg.add_empty_line()
872
873 if stream.event_context_type is not None:
874 self._generate_func_serialize_stream_event_context(stream)
875 self._cg.add_empty_line()
876
877 for ev in stream.events.values():
878 self._generate_func_get_event_size(stream, ev)
879 self._cg.add_empty_line()
880 self._generate_func_serialize_event(stream, ev)
881 self._cg.add_empty_line()
882 self._generate_func_trace(stream, ev)
883 self._cg.add_empty_line()
884
885
886 return self._cg.code
887
888 def get_header_filename(self):
889 return '{}.h'.format(self._cfg.prefix.rstrip('_'))
890
891 def get_bitfield_header_filename(self):
892 return '{}-bitfield.h'.format(self._cfg.prefix.rstrip('_'))
This page took 0.052546 seconds and 4 git commands to generate.