cgen.py: add type hints
[deliverable/barectf.git] / barectf / cgen.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 23
8c7c6ed2 24import barectf.template as barectf_template
4810b707 25import barectf.config as barectf_config
d6483c83 26import collections
acfb8213 27import copy
1624d186
PP
28from typing import List, Optional, Mapping, Callable, Any, Set, Tuple
29import typing
30from barectf.typing import Count, Alignment
4810b707
PP
31
32
d6483c83
PP
33# A tuple containing serialization and size computation function
34# templates for a given operation.
35_OpTemplates = collections.namedtuple('_OpTemplates', ['serialize', 'size'])
70e191bd
PP
36
37
d6483c83
PP
38# Base class of any operation within source code.
39#
40# Any operation has:
41#
42# * An offset at which to start to write within the current byte.
43#
44# * A field type.
45#
46# * A list of names which, when joined with `_`, form the generic C
47# source variable name.
48#
49# * Serialization and size computation templates to generate the
50# operation's source code for those functions.
51class _Op:
1624d186
PP
52 def __init__(self, offset_in_byte: Count, ft: barectf_config._FieldType, names: List[str],
53 templates: _OpTemplates):
acfb8213
PP
54 assert(offset_in_byte >= 0 and offset_in_byte < 8)
55 self._offset_in_byte = offset_in_byte
4810b707 56 self._ft = ft
d6483c83
PP
57 self._names = copy.copy(names)
58 self._templates = templates
e5aa0be3
PP
59
60 @property
1624d186 61 def offset_in_byte(self) -> Count:
acfb8213 62 return self._offset_in_byte
e5aa0be3 63
acfb8213 64 @property
1624d186 65 def ft(self) -> barectf_config._FieldType:
4810b707 66 return self._ft
acfb8213
PP
67
68 @property
1624d186 69 def names(self) -> List[str]:
acfb8213 70 return self._names
e5aa0be3 71
d6483c83 72 @property
1624d186 73 def top_name(self) -> str:
d6483c83 74 return self._names[-1]
e5aa0be3 75
1624d186 76 def _render_template(self, templ: barectf_template._Template, **kwargs) -> str:
d6483c83
PP
77 return templ.render(op=self, root_ft_prefixes=_RootFtPrefixes,
78 root_ft_prefix_names=_ROOT_FT_PREFIX_NAMES, **kwargs)
79
1624d186 80 def serialize_str(self, **kwargs) -> str:
d6483c83
PP
81 return self._render_template(self._templates.serialize, **kwargs)
82
1624d186 83 def size_str(self, **kwargs) -> str:
d6483c83
PP
84 return self._render_template(self._templates.size, **kwargs)
85
86
87# An "align" operation.
88class _AlignOp(_Op):
1624d186
PP
89 def __init__(self, offset_in_byte: Count, ft: barectf_config._FieldType, names: List[str],
90 templates: _OpTemplates, value: Alignment):
d6483c83 91 super().__init__(offset_in_byte, ft, names, templates)
acfb8213 92 self._value = value
e5aa0be3 93
acfb8213 94 @property
1624d186 95 def value(self) -> Alignment:
acfb8213 96 return self._value
e5aa0be3 97
e5aa0be3 98
d6483c83
PP
99# A "write" operation.
100class _WriteOp(_Op):
4810b707 101 pass
70e191bd 102
e5aa0be3 103
1624d186
PP
104_SpecSerializeWriteTemplates = Mapping[str, barectf_template._Template]
105_Ops = List[_Op]
106
107
d6483c83
PP
108# A builder of a chain of operations.
109#
728fc4a7
PP
110# Such a builder is closely connected to a `_CodeGen` object using it to
111# find generic templates.
d6483c83
PP
112#
113# Call append_root_ft() to make an operation builder append operations
114# to itself for each member, recursively, of the structure field type.
115#
116# Get an operation builder's operations with its `ops` property.
117class _OpsBuilder:
1624d186
PP
118 def __init__(self, cg: _CodeGen):
119 self._last_alignment: Optional[Alignment] = None
120 self._last_bit_array_size: Optional[Count] = None
121 self._ops: _Ops = []
122 self._names: List[str] = []
123 self._offset_in_byte = Count(0)
d6483c83 124 self._cg = cg
acfb8213 125
d6483c83 126 @property
1624d186 127 def ops(self) -> _Ops:
d6483c83
PP
128 return self._ops
129
130 # Creates and appends the operations for the members, recursively,
131 # of the root structure field type `ft` named `name`.
132 #
133 # `spec_serialize_write_templates` is a mapping of first level
134 # member names to specialized serialization "write" templates.
1624d186
PP
135 def append_root_ft(self, ft: barectf_config._FieldType, name: str,
136 spec_serialize_write_templates: Optional[_SpecSerializeWriteTemplates] = None):
4810b707 137 if ft is None:
acfb8213 138 return
e5aa0be3 139
d6483c83
PP
140 if spec_serialize_write_templates is None:
141 spec_serialize_write_templates = {}
142
143 assert type(ft) is barectf_config.StructureFieldType
144 assert len(self._names) == 0
145 self._append_ft(ft, name, spec_serialize_write_templates)
146
147 # Creates and appends the operations of a given field type `ft`
148 # named `name`.
149 #
150 # See append_root_ft() for `spec_serialize_write_templates`.
1624d186
PP
151 def _append_ft(self, ft: barectf_config._FieldType, name: str,
152 spec_serialize_write_templates: _SpecSerializeWriteTemplates):
153 def top_name() -> str:
d6483c83
PP
154 return self._names[-1]
155
156 # Appends a "write" operation for the field type `ft`.
157 #
158 # This function considers `spec_serialize_write_templates` to
159 # override generic templates.
1624d186 160 def append_write_op(ft: barectf_config._FieldType):
d6483c83
PP
161 assert type(ft) is not barectf_config.StructureFieldType
162 offset_in_byte = self._offset_in_byte
163
164 if isinstance(ft, barectf_config._BitArrayFieldType):
1624d186 165 self._offset_in_byte = Count((self._offset_in_byte + ft.size) % 8)
d6483c83 166
1624d186 167 serialize_write_templ: Optional[barectf_template._Template] = None
d6483c83
PP
168
169 if len(self._names) == 2:
170 serialize_write_templ = spec_serialize_write_templates.get(top_name())
171
172 if serialize_write_templ is None:
173 if isinstance(ft, barectf_config._IntegerFieldType):
174 serialize_write_templ = self._cg._serialize_write_int_statements_templ
175 elif type(ft) is barectf_config.RealFieldType:
176 serialize_write_templ = self._cg._serialize_write_real_statements_templ
177 else:
178 assert type(ft) is barectf_config.StringFieldType
179 serialize_write_templ = self._cg._serialize_write_string_statements_templ
180
181 size_write_templ = None
e5aa0be3 182
d6483c83
PP
183 if isinstance(ft, barectf_config._BitArrayFieldType):
184 size_write_templ = self._cg._size_write_bit_array_statements_templ
185 elif type(ft) is barectf_config.StringFieldType:
186 size_write_templ = self._cg._size_write_string_statements_templ
187
188 self._ops.append(_WriteOp(offset_in_byte, ft, self._names,
189 _OpTemplates(serialize_write_templ, size_write_templ)))
190
191 # Creates and appends an "align" operation for the field type
192 # `ft` if needed.
193 #
194 # This function updates the builder's state.
1624d186
PP
195 def try_append_align_op(alignment: Alignment, do_align: bool,
196 ft: barectf_config._FieldType):
197 def align(v: Count, alignment: Alignment) -> Count:
198 return Count((v + (alignment - 1)) & -alignment)
d6483c83
PP
199
200 offset_in_byte = self._offset_in_byte
1624d186 201 self._offset_in_byte = Count(align(self._offset_in_byte, alignment) % 8)
d6483c83
PP
202
203 if do_align and alignment > 1:
204 self._ops.append(_AlignOp(offset_in_byte, ft, self._names,
205 _OpTemplates(self._cg._serialize_align_statements_templ,
206 self._cg._size_align_statements_templ),
207 alignment))
acfb8213 208
d6483c83
PP
209 # Returns whether or not, considering the alignment requirement
210 # `align_req` and the builder's current state, we must create
211 # and append an "align" operation.
1624d186
PP
212 def must_align(align_req: Alignment) -> bool:
213 return self._last_alignment != align_req or typing.cast(Count, self._last_bit_array_size) % align_req != 0
acfb8213 214
d6483c83
PP
215 # push field type's name to the builder's name stack initially
216 self._names.append(name)
acfb8213 217
4810b707 218 if isinstance(ft, (barectf_config.StringFieldType, barectf_config._ArrayFieldType)):
d6483c83
PP
219 assert type(ft) is barectf_config.StringFieldType or top_name() == 'uuid'
220
221 # strings and arrays are always byte-aligned
1624d186
PP
222 do_align = must_align(Alignment(8))
223 self._last_alignment = Alignment(8)
224 self._last_bit_array_size = Count(8)
225 try_append_align_op(Alignment(8), do_align, ft)
d6483c83 226 append_write_op(ft)
4810b707 227 else:
d6483c83 228 do_align = must_align(ft.alignment)
4810b707
PP
229 self._last_alignment = ft.alignment
230
231 if type(ft) is barectf_config.StructureFieldType:
1624d186 232 self._last_bit_array_size = typing.cast(Count, ft.alignment)
acfb8213 233 else:
1624d186
PP
234 assert isinstance(ft, barectf_config._BitArrayFieldType)
235 ft = typing.cast(barectf_config._BitArrayFieldType, ft)
4810b707 236 self._last_bit_array_size = ft.size
70e191bd 237
d6483c83 238 try_append_align_op(ft.alignment, do_align, ft)
70e191bd 239
4810b707 240 if type(ft) is barectf_config.StructureFieldType:
1624d186 241 ft = typing.cast(barectf_config.StructureFieldType, ft)
4810b707 242 for member_name, member in ft.members.items():
d6483c83 243 self._append_ft(member.field_type, member_name, spec_serialize_write_templates)
70e191bd 244 else:
d6483c83
PP
245 append_write_op(ft)
246
247 # exiting for this field type: pop its name
248 del self._names[-1]
70e191bd 249
70e191bd 250
d6483c83
PP
251# The operations for an event.
252#
253# The available operations are:
254#
255# * Specific context operations.
256# * Payload operations.
1624d186
PP
257class _EvOps:
258 def __init__(self, spec_ctx_ops: _Ops, payload_ops: _Ops):
d6483c83
PP
259 self._spec_ctx_ops = copy.copy(spec_ctx_ops)
260 self._payload_ops = copy.copy(payload_ops)
70e191bd 261
d6483c83 262 @property
1624d186 263 def spec_ctx_ops(self) -> _Ops:
d6483c83 264 return self._spec_ctx_ops
acfb8213 265
d6483c83 266 @property
1624d186 267 def payload_ops(self) -> _Ops:
d6483c83 268 return self._payload_ops
acfb8213 269
70e191bd 270
1624d186
PP
271_EvOpsMap = Mapping[barectf_config.EventType, _EvOps]
272
273
d6483c83
PP
274# The operations for a stream.
275#
276# The available operations are:
277#
278# * Packet header operations.
279# * Packet context operations.
280# * Event header operations.
281# * Event common context operations.
1624d186 282# * Event operations (`_EvOps`).
d6483c83 283class _StreamOps:
1624d186
PP
284 def __init__(self, pkt_header_ops: _Ops, pkt_ctx_ops: _Ops, ev_header_ops: _Ops,
285 ev_common_ctx_ops: _Ops, ev_ops: _EvOpsMap):
d6483c83
PP
286 self._pkt_header_ops = copy.copy(pkt_header_ops)
287 self._pkt_ctx_ops = copy.copy(pkt_ctx_ops)
288 self._ev_header_ops = copy.copy(ev_header_ops)
289 self._ev_common_ctx_ops = copy.copy(ev_common_ctx_ops)
290 self._ev_ops = copy.copy(ev_ops)
70e191bd 291
d6483c83 292 @property
1624d186 293 def pkt_header_ops(self) -> _Ops:
d6483c83
PP
294 return self._pkt_header_ops
295
296 @property
1624d186 297 def pkt_ctx_ops(self) -> _Ops:
d6483c83
PP
298 return self._pkt_ctx_ops
299
300 @property
1624d186 301 def ev_header_ops(self) -> _Ops:
d6483c83
PP
302 return self._ev_header_ops
303
304 @property
1624d186 305 def ev_common_ctx_ops(self) -> _Ops:
d6483c83
PP
306 return self._ev_common_ctx_ops
307
308 @property
1624d186 309 def ev_ops(self) -> _EvOpsMap:
d6483c83
PP
310 return self._ev_ops
311
312
313# The C variable name prefixes for the six kinds of root field types.
1b49c7b8 314class _RootFtPrefixes:
1c650e47
PP
315 PH = 'ph'
316 PC = 'pc'
317 EH = 'eh'
318 ECC = 'ecc'
319 SC = 'sc'
320 P = 'p'
d6483c83
PP
321
322
323# The human-readable names of the `_RootFtPrefixes` members.
324_ROOT_FT_PREFIX_NAMES = {
1c650e47
PP
325 _RootFtPrefixes.PH: 'packet header',
326 _RootFtPrefixes.PC: 'packet context',
327 _RootFtPrefixes.EH: 'event header',
328 _RootFtPrefixes.ECC: 'event common context',
329 _RootFtPrefixes.SC: 'specific context',
330 _RootFtPrefixes.P: 'payload',
acfb8213 331}
e5aa0be3
PP
332
333
d6483c83
PP
334# A named function parameter for a given field type.
335_FtParam = collections.namedtuple('_FtParam', ['ft', 'name'])
336
337
338# A C code generator.
339#
340# Such a code generator can generate:
341#
728fc4a7
PP
342# * The bitfield header (gen_bitfield_header()).
343# * The public header (gen_header()).
344# * The source code (gen_src()).
345class _CodeGen:
1624d186 346 def __init__(self, cfg: barectf_config.Configuration):
e5aa0be3 347 self._cfg = cfg
d6483c83 348 self._iden_prefix = cfg.options.code_generation_options.identifier_prefix
1624d186 349 self._templ_filters: Mapping[str, Callable[..., Any]] = {
d6483c83
PP
350 'ft_c_type': self._ft_c_type,
351 'open_func_params_str': self._open_func_params_str,
352 'trace_func_params_str': self._trace_func_params_str,
353 'serialize_ev_common_ctx_func_params_str': self._serialize_ev_common_ctx_func_params_str,
1b49c7b8 354 }
d6483c83
PP
355 self._func_proto_params_templ = self._create_template('func-proto-params.j2')
356 self._serialize_align_statements_templ = self._create_template('serialize-align-statements.j2')
357 self._serialize_write_int_statements_templ = self._create_template('serialize-write-int-statements.j2')
358 self._serialize_write_real_statements_templ = self._create_template('serialize-write-real-statements.j2')
359 self._serialize_write_string_statements_templ = self._create_template('serialize-write-string-statements.j2')
360 self._serialize_write_magic_statements_templ = self._create_template('serialize-write-magic-statements.j2')
361 self._serialize_write_uuid_statements_templ = self._create_template('serialize-write-uuid-statements.j2')
362 self._serialize_write_stream_type_id_statements_templ = self._create_template('serialize-write-stream-type-id-statements.j2')
363 self._serialize_write_time_statements_templ = self._create_template('serialize-write-time-statements.j2')
364 self._serialize_write_packet_size_statements_templ = self._create_template('serialize-write-packet-size-statements.j2')
365 self._serialize_write_skip_save_statements_templ = self._create_template('serialize-write-skip-save-statements.j2')
366 self._serialize_write_ev_type_id_statements_templ = self._create_template('serialize-write-ev-type-id-statements.j2')
367 self._size_align_statements_templ = self._create_template('size-align-statements.j2')
368 self._size_write_bit_array_statements_templ = self._create_template('size-write-bit-array-statements.j2')
369 self._size_write_string_statements_templ = self._create_template('size-write-string-statements.j2')
370
371 # Creates and returns a template named `name` which is a file
372 # template if `is_file_template` is `True`.
373 #
374 # `name` is the file name, including the `.j2` extension, within the
375 # `c` directory.
376 #
377 # Such a template has the filters custom filters
378 # `self._templ_filters`.
1624d186
PP
379 def _create_template_base(self, name: str,
380 is_file_template: bool) -> barectf_template._Template:
d6483c83
PP
381 return barectf_template._Template(f'c/{name}', is_file_template, self._cfg,
382 self._templ_filters)
383
384 # Creates and returns a non-file template named `name`.
385 #
386 # See _create_template_base() for `name`.
8c7c6ed2 387 def _create_template(self, name: str) -> barectf_template._Template:
d6483c83 388 return self._create_template_base(name, False)
8c7c6ed2 389
d6483c83
PP
390 # Creates and returns a file template named `name`.
391 #
392 # See _create_template_base() for `name`.
8c7c6ed2 393 def _create_file_template(self, name: str) -> barectf_template._Template:
d6483c83 394 return self._create_template_base(name, True)
8c7c6ed2 395
d6483c83 396 # Trace type of this code generator's barectf configuration.
4810b707 397 @property
1624d186 398 def _trace_type(self) -> barectf_config.TraceType:
4810b707 399 return self._cfg.trace.type
27bc6f1e 400
e18cf9d6
PP
401 # Returns the C type for the field type `ft`, returning a `const` C
402 # type if `is_const` is `True`.
1624d186 403 def _ft_c_type(self, ft: barectf_config._FieldType, is_const: bool = False) -> str:
e18cf9d6
PP
404 const_beg_str = 'const '
405
4810b707 406 if isinstance(ft, barectf_config._IntegerFieldType):
1624d186 407 ft = typing.cast(barectf_config._IntegerFieldType, ft)
4810b707
PP
408 sign_prefix = 'u' if isinstance(ft, barectf_config.UnsignedIntegerFieldType) else ''
409
410 if ft.size <= 8:
411 sz = 8
412 elif ft.size <= 16:
413 sz = 16
414 elif ft.size <= 32:
415 sz = 32
416 else:
d6483c83 417 assert ft.size <= 64
4810b707
PP
418 sz = 64
419
e18cf9d6 420 return f'{const_beg_str if is_const else ""}{sign_prefix}int{sz}_t'
4810b707 421 elif type(ft) is barectf_config.RealFieldType:
1624d186
PP
422 ft = typing.cast(barectf_config.RealFieldType, ft)
423
4810b707 424 if ft.size == 32 and ft.alignment == 32:
e18cf9d6 425 c_type = 'float'
4810b707 426 elif ft.size == 64 and ft.alignment == 64:
e18cf9d6 427 c_type = 'double'
4810b707 428 else:
e18cf9d6
PP
429 c_type = 'uint64_t'
430
431 return f'{const_beg_str if is_const else ""}{c_type}'
e5aa0be3 432 else:
4810b707 433 assert type(ft) is barectf_config.StringFieldType
e18cf9d6 434 return f'const char *{" const" if is_const else ""}'
e5aa0be3 435
d6483c83
PP
436 # Returns the function prototype parameters for the members of the
437 # root structure field type `root_ft`.
438 #
439 # Each parameter has the prefix `name_prefix` followed with `_`.
440 #
441 # Members of which the name is in `exclude_set` are excluded.
1624d186
PP
442 def _proto_params_str(self, root_ft: Optional[barectf_config.StructureFieldType],
443 name_prefix: str, const_params: bool,
444 exclude_set: Optional[Set[str]] = None, only_dyn: bool = False) -> str:
d6483c83 445 if root_ft is None:
1624d186 446 return ''
e5aa0be3 447
4810b707
PP
448 if exclude_set is None:
449 exclude_set = set()
450
d6483c83 451 params = []
e5aa0be3 452
d6483c83 453 for member_name, member in root_ft.members.items():
4810b707 454 if member_name in exclude_set:
e5aa0be3
PP
455 continue
456
b622b24f
PP
457 if only_dyn and not member.field_type.size_is_dynamic:
458 continue
459
d6483c83 460 params.append(_FtParam(member.field_type, member_name))
e5aa0be3 461
e18cf9d6
PP
462 return self._func_proto_params_templ.render(params=params, prefix=name_prefix,
463 const_params=const_params)
4810b707 464
d6483c83
PP
465 # Returns the packet opening function prototype parameters for the
466 # stream type `stream_type`.
1624d186
PP
467 def _open_func_params_str(self, stream_type: barectf_config.StreamType,
468 const_params: bool) -> str:
d6483c83 469 parts = []
1c650e47 470 parts.append(self._proto_params_str(self._trace_type._pkt_header_ft, _RootFtPrefixes.PH,
e18cf9d6 471 const_params, {'magic', 'stream_id', 'uuid'}))
e5aa0be3 472
4810b707
PP
473 exclude_set = {
474 'timestamp_begin',
475 'timestamp_end',
476 'packet_size',
477 'content_size',
478 'events_discarded',
479 }
1c650e47 480 parts.append(self._proto_params_str(stream_type._pkt_ctx_ft, _RootFtPrefixes.PC,
e18cf9d6 481 const_params, exclude_set))
d6483c83 482 return ''.join(parts)
e5aa0be3 483
d6483c83
PP
484 # Returns the tracing function prototype parameters for the stream
485 # and event types `stream_ev_types`.
1624d186
PP
486 def _trace_func_params_str(self, stream_ev_types: Tuple[barectf_config.StreamType,
487 barectf_config.EventType],
488 const_params: bool, only_dyn: bool = False):
d6483c83
PP
489 stream_type = stream_ev_types[0]
490 ev_type = stream_ev_types[1]
491 parts = []
e5aa0be3 492
4810b707 493 if stream_type._ev_header_ft is not None:
1c650e47 494 parts.append(self._proto_params_str(stream_type._ev_header_ft, _RootFtPrefixes.EH,
b622b24f
PP
495 const_params, {'id', 'timestamp'},
496 only_dyn=only_dyn))
4810b707
PP
497
498 if stream_type.event_common_context_field_type is not None:
d6483c83 499 parts.append(self._proto_params_str(stream_type.event_common_context_field_type,
b622b24f
PP
500 _RootFtPrefixes.ECC, const_params,
501 only_dyn=only_dyn))
4810b707
PP
502
503 if ev_type.specific_context_field_type is not None:
d6483c83 504 parts.append(self._proto_params_str(ev_type.specific_context_field_type,
b622b24f
PP
505 _RootFtPrefixes.SC, const_params,
506 only_dyn=only_dyn))
4810b707
PP
507
508 if ev_type.payload_field_type is not None:
e18cf9d6 509 parts.append(self._proto_params_str(ev_type.payload_field_type, _RootFtPrefixes.P,
b622b24f 510 const_params, only_dyn=only_dyn))
e5aa0be3 511
d6483c83 512 return ''.join(parts)
4810b707 513
d6483c83
PP
514 # Returns the event header serialization function prototype
515 # parameters for the stream type `stream_type`.
1624d186
PP
516 def _serialize_ev_common_ctx_func_params_str(self, stream_type: barectf_config.StreamType,
517 const_params: bool) -> str:
d6483c83 518 return self._proto_params_str(stream_type.event_common_context_field_type,
e18cf9d6 519 _RootFtPrefixes.ECC, const_params);
e5aa0be3 520
d6483c83 521 # Generates the bitfield header file contents.
1624d186 522 def gen_bitfield_header(self) -> str:
d6483c83 523 return self._create_file_template('bitfield.h.j2').render()
e5aa0be3 524
d6483c83 525 # Generates the public header file contents.
1624d186 526 def gen_header(self) -> str:
d6483c83 527 return self._create_file_template('barectf.h.j2').render(root_ft_prefixes=_RootFtPrefixes)
3cb793a1 528
d6483c83 529 # Generates the source code file contents.
1624d186 530 def gen_src(self, header_file_name: str, bitfield_header_file_name: str) -> str:
d6483c83
PP
531 # Creates and returns the operations for all the stream and for
532 # all their events.
1624d186 533 def create_stream_ops() -> Mapping[barectf_config.StreamType, _StreamOps]:
d6483c83
PP
534 stream_ser_ops = {}
535
536 for stream_type in self._trace_type.stream_types:
537 pkt_header_ser_ops = []
538 builder = _OpsBuilder(self)
539 pkt_header_ft = self._trace_type._pkt_header_ft
540
541 # packet header serialization operations
542 if pkt_header_ft is not None:
543 spec_serialize_write_templates = {
544 'magic': self._serialize_write_magic_statements_templ,
545 'uuid': self._serialize_write_uuid_statements_templ,
546 'stream_id': self._serialize_write_stream_type_id_statements_templ,
547 }
1c650e47 548 builder.append_root_ft(pkt_header_ft, _RootFtPrefixes.PH,
d6483c83
PP
549 spec_serialize_write_templates)
550 pkt_header_ser_ops = copy.copy(builder.ops)
551
552 # packet context serialization operations
553 first_op_index = len(builder.ops)
554 spec_serialize_write_templates = {
555 'timestamp_begin': self._serialize_write_time_statements_templ,
556 'packet_size': self._serialize_write_packet_size_statements_templ,
557 'timestamp_end': self._serialize_write_skip_save_statements_templ,
558 'events_discarded': self._serialize_write_skip_save_statements_templ,
559 'content_size': self._serialize_write_skip_save_statements_templ,
560 }
1c650e47 561 builder.append_root_ft(stream_type._pkt_ctx_ft, _RootFtPrefixes.PC,
d6483c83
PP
562 spec_serialize_write_templates)
563 pkt_ctx_ser_ops = copy.copy(builder.ops[first_op_index:])
564
565 # event header serialization operations
566 builder = _OpsBuilder(self)
567 ev_header_ser_ops = []
568
569 if stream_type._ev_header_ft is not None:
570 spec_serialize_write_templates = {
571 'timestamp': self._serialize_write_time_statements_templ,
572 'id': self._serialize_write_ev_type_id_statements_templ,
573 }
1c650e47 574 builder.append_root_ft(stream_type._ev_header_ft, _RootFtPrefixes.EH,
d6483c83
PP
575 spec_serialize_write_templates)
576 ev_header_ser_ops = copy.copy(builder.ops)
577
578 # event common context serialization operations
579 ev_common_ctx_ser_ops = []
580
581 if stream_type.event_common_context_field_type is not None:
582 first_op_index = len(builder.ops)
583 builder.append_root_ft(stream_type.event_common_context_field_type,
1c650e47 584 _RootFtPrefixes.ECC)
d6483c83
PP
585 ev_common_ctx_ser_ops = copy.copy(builder.ops[first_op_index:])
586
587 # serialization operations specific to each event type
588 ev_ser_ops = {}
589
590 for ev_type in stream_type.event_types:
591 ev_builder = copy.copy(builder)
592
593 # specific context serialization operations
594 spec_ctx_ser_ops = []
595
596 if ev_type.specific_context_field_type is not None:
597 first_op_index = len(ev_builder.ops)
598 ev_builder.append_root_ft(ev_type.specific_context_field_type,
1c650e47 599 _RootFtPrefixes.SC)
d6483c83
PP
600 spec_ctx_ser_ops = copy.copy(ev_builder.ops[first_op_index:])
601
602 # payload serialization operations
603 payload_ser_ops = []
604
605 if ev_type.payload_field_type is not None:
606 first_op_index = len(ev_builder.ops)
1c650e47 607 ev_builder.append_root_ft(ev_type.payload_field_type, _RootFtPrefixes.P)
d6483c83
PP
608 payload_ser_ops = copy.copy(ev_builder.ops[first_op_index:])
609
1624d186 610 ev_ser_ops[ev_type] = _EvOps(spec_ctx_ser_ops, payload_ser_ops)
d6483c83
PP
611
612 stream_ser_ops[stream_type] = _StreamOps(pkt_header_ser_ops, pkt_ctx_ser_ops,
613 ev_header_ser_ops, ev_common_ctx_ser_ops,
614 ev_ser_ops)
615
616 return stream_ser_ops
617
618 # Returns the "write" operation for the packet context member
619 # named `member_name` within the stream type `stream_type`.
1624d186
PP
620 def stream_op_pkt_ctx_op(stream_type: barectf_config.StreamType, member_name: str) -> _Op:
621 ret_op = None
622
d6483c83
PP
623 for op in stream_ops[stream_type].pkt_ctx_ops:
624 if op.top_name == member_name and type(op) is _WriteOp:
1624d186
PP
625 ret_op = op
626 break
627
628 assert ret_op is not None
629 return typing.cast(_Op, ret_op)
d6483c83
PP
630
631 stream_ops = create_stream_ops()
632 return self._create_file_template('barectf.c.j2').render(header_file_name=header_file_name,
633 bitfield_header_file_name=bitfield_header_file_name,
634 root_ft_prefixes=_RootFtPrefixes,
635 root_ft_prefix_names=_ROOT_FT_PREFIX_NAMES,
636 stream_ops=stream_ops,
637 stream_op_pkt_ctx_op=stream_op_pkt_ctx_op)
This page took 0.070075 seconds and 4 git commands to generate.