Re-format new C++ files
[babeltrace.git] / src / plugins / ctf / common / metadata / visitor-generate-ir.cpp
CommitLineData
e98a2d6e 1/*
0235b0db 2 * SPDX-License-Identifier: MIT
e98a2d6e 3 *
0235b0db
MJ
4 * Copyright 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * Copyright 2015-2018 Philippe Proulx <philippe.proulx@efficios.com>
e98a2d6e 6 *
0235b0db 7 * Common Trace Format metadata visitor (generates CTF IR objects).
e98a2d6e
PP
8 */
9
4164020e 10#define BT_COMP_LOG_SELF_COMP (ctx->log_cfg.self_comp)
50f6fce8 11#define BT_COMP_LOG_SELF_COMP_CLASS (ctx->log_cfg.self_comp_class)
4164020e
SM
12#define BT_LOG_OUTPUT_LEVEL (ctx->log_cfg.log_level)
13#define BT_LOG_TAG "PLUGIN/CTF/META/IR-VISITOR"
d9c39b0a 14#include "logging/comp-logging.h"
08da4f77 15
e98a2d6e
PP
16#include <stdio.h>
17#include <unistd.h>
18#include <string.h>
c55a9f58 19#include <stdbool.h>
e98a2d6e
PP
20#include <stdlib.h>
21#include <ctype.h>
578e048b 22#include "common/assert.h"
e98a2d6e
PP
23#include <glib.h>
24#include <inttypes.h>
25#include <errno.h>
578e048b 26#include "common/common.h"
6162e6b7 27#include "common/uuid.h"
578e048b 28#include "compat/endian.h"
3fadfbc0 29#include <babeltrace2/babeltrace.h>
e98a2d6e 30
087cd0f5
SM
31#include "logging.hpp"
32#include "scanner.hpp"
33#include "ast.hpp"
34#include "decoder.hpp"
35#include "ctf-meta.hpp"
36#include "ctf-meta-visitors.hpp"
e98a2d6e
PP
37
38/* Bit value (left shift) */
4164020e 39#define _BV(_val) (1 << (_val))
e98a2d6e
PP
40
41/* Bit is set in a set of bits */
4164020e 42#define _IS_SET(_set, _mask) (*(_set) & (_mask))
e98a2d6e
PP
43
44/* Set bit in a set of bits */
4164020e 45#define _SET(_set, _mask) (*(_set) |= (_mask))
e98a2d6e 46
44c440bc 47/* Try to push scope, or go to the `error` label */
4164020e
SM
48#define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
49 do { \
50 ret = ctx_push_scope(ctx); \
51 if (ret) { \
52 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot push scope."); \
53 goto error; \
54 } \
55 } while (0)
44c440bc 56
e98a2d6e 57/* Bits for verifying existing attributes in various declarations */
4164020e
SM
58enum
59{
60 _CLOCK_NAME_SET = _BV(0),
61 _CLOCK_UUID_SET = _BV(1),
62 _CLOCK_FREQ_SET = _BV(2),
63 _CLOCK_PRECISION_SET = _BV(3),
64 _CLOCK_OFFSET_S_SET = _BV(4),
65 _CLOCK_OFFSET_SET = _BV(5),
66 _CLOCK_ABSOLUTE_SET = _BV(6),
67 _CLOCK_DESCRIPTION_SET = _BV(7),
e98a2d6e
PP
68};
69
4164020e
SM
70enum
71{
72 _INTEGER_ALIGN_SET = _BV(0),
73 _INTEGER_SIZE_SET = _BV(1),
74 _INTEGER_BASE_SET = _BV(2),
75 _INTEGER_ENCODING_SET = _BV(3),
76 _INTEGER_BYTE_ORDER_SET = _BV(4),
77 _INTEGER_SIGNED_SET = _BV(5),
78 _INTEGER_MAP_SET = _BV(6),
e98a2d6e
PP
79};
80
4164020e
SM
81enum
82{
83 _FLOAT_ALIGN_SET = _BV(0),
84 _FLOAT_MANT_DIG_SET = _BV(1),
85 _FLOAT_EXP_DIG_SET = _BV(2),
86 _FLOAT_BYTE_ORDER_SET = _BV(3),
e98a2d6e
PP
87};
88
4164020e
SM
89enum
90{
91 _STRING_ENCODING_SET = _BV(0),
e98a2d6e
PP
92};
93
4164020e
SM
94enum
95{
96 _TRACE_MINOR_SET = _BV(0),
97 _TRACE_MAJOR_SET = _BV(1),
98 _TRACE_BYTE_ORDER_SET = _BV(2),
99 _TRACE_UUID_SET = _BV(3),
100 _TRACE_PACKET_HEADER_SET = _BV(4),
e98a2d6e
PP
101};
102
4164020e
SM
103enum
104{
105 _STREAM_ID_SET = _BV(0),
106 _STREAM_PACKET_CONTEXT_SET = _BV(1),
107 _STREAM_EVENT_HEADER_SET = _BV(2),
108 _STREAM_EVENT_CONTEXT_SET = _BV(3),
e98a2d6e
PP
109};
110
4164020e
SM
111enum
112{
113 _EVENT_NAME_SET = _BV(0),
114 _EVENT_ID_SET = _BV(1),
115 _EVENT_MODEL_EMF_URI_SET = _BV(2),
116 _EVENT_STREAM_ID_SET = _BV(3),
117 _EVENT_LOG_LEVEL_SET = _BV(4),
118 _EVENT_CONTEXT_SET = _BV(5),
119 _EVENT_FIELDS_SET = _BV(6),
e98a2d6e
PP
120};
121
4164020e
SM
122enum loglevel
123{
124 LOG_LEVEL_EMERG = 0,
125 LOG_LEVEL_ALERT = 1,
126 LOG_LEVEL_CRIT = 2,
127 LOG_LEVEL_ERR = 3,
128 LOG_LEVEL_WARNING = 4,
129 LOG_LEVEL_NOTICE = 5,
130 LOG_LEVEL_INFO = 6,
131 LOG_LEVEL_DEBUG_SYSTEM = 7,
132 LOG_LEVEL_DEBUG_PROGRAM = 8,
133 LOG_LEVEL_DEBUG_PROCESS = 9,
134 LOG_LEVEL_DEBUG_MODULE = 10,
135 LOG_LEVEL_DEBUG_UNIT = 11,
136 LOG_LEVEL_DEBUG_FUNCTION = 12,
137 LOG_LEVEL_DEBUG_LINE = 13,
138 LOG_LEVEL_DEBUG = 14,
139 _NR_LOGLEVELS = 15,
c3c30b08
MD
140};
141
5cd6d0e5 142/* Prefixes of class aliases */
4164020e
SM
143#define _PREFIX_ALIAS 'a'
144#define _PREFIX_ENUM 'e'
145#define _PREFIX_STRUCT 's'
146#define _PREFIX_VARIANT 'v'
e98a2d6e
PP
147
148/* First entry in a BT list */
4164020e 149#define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) bt_list_entry((_ptr)->next, _class, _member)
e98a2d6e 150
4164020e
SM
151#define _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \
152 _BT_COMP_LOGE_APPEND_CAUSE_LINENO( \
153 (_node)->lineno, "Duplicate attribute in %s: attr-name=\"%s\"", _entity, _attr)
28973adf 154
4164020e 155#define _BT_COMP_LOGE_NODE(_node, _msg, args...) _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ##args)
28973adf 156
4164020e
SM
157#define _BT_COMP_LOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
158 _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, _msg, ##args)
50f6fce8 159
4164020e 160#define _BT_COMP_LOGW_NODE(_node, _msg, args...) _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ##args)
28973adf 161
4164020e 162#define _BT_COMP_LOGT_NODE(_node, _msg, args...) _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ##args)
e98a2d6e
PP
163
164/*
165 * Declaration scope of a visitor context. This represents a TSDL
166 * lexical scope, so that aliases and named structures, variants,
167 * and enumerations may be registered and looked up hierarchically.
168 */
4164020e
SM
169struct ctx_decl_scope
170{
171 /*
172 * Alias name to field class.
173 *
174 * GQuark -> struct ctf_field_class * (owned by this)
175 */
176 GHashTable *decl_map;
177
178 /* Parent scope; NULL if this is the root declaration scope */
179 struct ctx_decl_scope *parent_scope;
e98a2d6e
PP
180};
181
182/*
1e649dff 183 * Visitor context (private).
e98a2d6e 184 */
4164020e
SM
185struct ctf_visitor_generate_ir
186{
187 struct meta_log_config log_cfg;
f7b785ac 188
4164020e
SM
189 /* Trace IR trace class being filled (owned by this) */
190 bt_trace_class *trace_class;
e98a2d6e 191
4164020e
SM
192 /* CTF meta trace being filled (owned by this) */
193 struct ctf_trace_class *ctf_tc;
44c440bc 194
4164020e
SM
195 /* Current declaration scope (top of the stack) (owned by this) */
196 struct ctx_decl_scope *current_scope;
e98a2d6e 197
4164020e
SM
198 /* True if trace declaration is visited */
199 bool is_trace_visited;
e98a2d6e 200
4164020e
SM
201 /* True if this is an LTTng trace */
202 bool is_lttng;
f4421ff3 203
4164020e
SM
204 /* Config passed by the user */
205 struct ctf_metadata_decoder_config decoder_config;
e98a2d6e
PP
206};
207
1e649dff
PP
208/*
209 * Visitor (public).
210 */
44c440bc 211struct ctf_visitor_generate_ir;
1e649dff 212
e98a2d6e
PP
213/**
214 * Creates a new declaration scope.
215 *
216 * @param par_scope Parent scope (NULL if creating a root scope)
217 * @returns New declaration scope, or NULL on error
218 */
4164020e
SM
219static struct ctx_decl_scope *ctx_decl_scope_create(struct ctf_visitor_generate_ir *ctx,
220 struct ctx_decl_scope *par_scope)
e98a2d6e 221{
4164020e 222 struct ctx_decl_scope *scope;
e98a2d6e 223
4164020e
SM
224 scope = g_new(struct ctx_decl_scope, 1);
225 if (!scope) {
226 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate one declaration scope.");
227 goto end;
228 }
e98a2d6e 229
4164020e
SM
230 scope->decl_map = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
231 (GDestroyNotify) ctf_field_class_destroy);
232 scope->parent_scope = par_scope;
e98a2d6e
PP
233
234end:
4164020e 235 return scope;
e98a2d6e
PP
236}
237
238/**
239 * Destroys a declaration scope.
240 *
241 * This function does not destroy the parent scope.
242 *
243 * @param scope Scope to destroy
244 */
4164020e 245static void ctx_decl_scope_destroy(struct ctx_decl_scope *scope)
e98a2d6e 246{
4164020e
SM
247 if (!scope) {
248 goto end;
249 }
e98a2d6e 250
4164020e
SM
251 g_hash_table_destroy(scope->decl_map);
252 g_free(scope);
e98a2d6e
PP
253
254end:
4164020e 255 return;
e98a2d6e
PP
256}
257
258/**
259 * Returns the GQuark of a prefixed alias.
260 *
261 * @param prefix Prefix character
262 * @param name Name
263 * @returns Associated GQuark, or 0 on error
264 */
4164020e
SM
265static GQuark get_prefixed_named_quark(struct ctf_visitor_generate_ir *ctx, char prefix,
266 const char *name)
e98a2d6e 267{
4164020e 268 GQuark qname = 0;
e98a2d6e 269
4164020e 270 BT_ASSERT(name);
e98a2d6e 271
4164020e
SM
272 /* Prefix character + original string + '\0' */
273 char *prname = g_new(char, strlen(name) + 2);
274 if (!prname) {
275 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate a string.");
276 goto end;
277 }
e98a2d6e 278
4164020e
SM
279 sprintf(prname, "%c%s", prefix, name);
280 qname = g_quark_from_string(prname);
281 g_free(prname);
e98a2d6e
PP
282
283end:
4164020e 284 return qname;
e98a2d6e
PP
285}
286
287/**
5cd6d0e5 288 * Looks up a prefixed class alias within a declaration scope.
e98a2d6e
PP
289 *
290 * @param scope Declaration scope
291 * @param prefix Prefix character
292 * @param name Alias name
44c440bc
PP
293 * @param levels Number of levels to dig into (-1 means infinite)
294 * @param copy True to return a copy
295 * @returns Declaration (owned by caller if \p copy is true),
296 * or NULL if not found
e98a2d6e 297 */
4164020e
SM
298static struct ctf_field_class *
299ctx_decl_scope_lookup_prefix_alias(struct ctf_visitor_generate_ir *ctx,
300 struct ctx_decl_scope *scope, char prefix, const char *name,
301 int levels, bool copy)
e98a2d6e 302{
4164020e
SM
303 GQuark qname = 0;
304 int cur_levels = 0;
305 struct ctf_field_class *decl = NULL;
306 struct ctx_decl_scope *cur_scope = scope;
307
308 BT_ASSERT(scope);
309 BT_ASSERT(name);
310 qname = get_prefixed_named_quark(ctx, prefix, name);
311 if (!qname) {
312 goto end;
313 }
314
315 if (levels < 0) {
316 levels = INT_MAX;
317 }
318
319 while (cur_scope && cur_levels < levels) {
320 decl = (ctf_field_class *) g_hash_table_lookup(cur_scope->decl_map,
321 (gconstpointer) GUINT_TO_POINTER(qname));
322 if (decl) {
323 /* Caller's reference */
324 if (copy) {
325 decl = ctf_field_class_copy(decl);
326 BT_ASSERT(decl);
327 }
328
329 goto end;
330 }
331
332 cur_scope = cur_scope->parent_scope;
333 cur_levels++;
334 }
e98a2d6e 335
44c440bc 336end:
4164020e 337 return decl;
e98a2d6e
PP
338}
339
340/**
5cd6d0e5 341 * Looks up a class alias within a declaration scope.
e98a2d6e
PP
342 *
343 * @param scope Declaration scope
344 * @param name Alias name
44c440bc
PP
345 * @param levels Number of levels to dig into (-1 means infinite)
346 * @param copy True to return a copy
347 * @returns Declaration (owned by caller if \p copy is true),
348 * or NULL if not found
e98a2d6e 349 */
4164020e
SM
350static struct ctf_field_class *ctx_decl_scope_lookup_alias(struct ctf_visitor_generate_ir *ctx,
351 struct ctx_decl_scope *scope,
352 const char *name, int levels, bool copy)
e98a2d6e 353{
4164020e 354 return ctx_decl_scope_lookup_prefix_alias(ctx, scope, _PREFIX_ALIAS, name, levels, copy);
e98a2d6e
PP
355}
356
357/**
358 * Looks up an enumeration within a declaration scope.
359 *
360 * @param scope Declaration scope
361 * @param name Enumeration name
44c440bc
PP
362 * @param levels Number of levels to dig into (-1 means infinite)
363 * @param copy True to return a copy
364 * @returns Declaration (owned by caller if \p copy is true),
365 * or NULL if not found
e98a2d6e 366 */
4164020e
SM
367static struct ctf_field_class_enum *ctx_decl_scope_lookup_enum(struct ctf_visitor_generate_ir *ctx,
368 struct ctx_decl_scope *scope,
369 const char *name, int levels,
370 bool copy)
e98a2d6e 371{
4164020e
SM
372 return ctf_field_class_as_enum(
373 ctx_decl_scope_lookup_prefix_alias(ctx, scope, _PREFIX_ENUM, name, levels, copy));
e98a2d6e
PP
374}
375
376/**
377 * Looks up a structure within a declaration scope.
378 *
379 * @param scope Declaration scope
380 * @param name Structure name
44c440bc
PP
381 * @param levels Number of levels to dig into (-1 means infinite)
382 * @param copy True to return a copy
383 * @returns Declaration (owned by caller if \p copy is true),
384 * or NULL if not found
e98a2d6e 385 */
4164020e
SM
386static struct ctf_field_class_struct *
387ctx_decl_scope_lookup_struct(struct ctf_visitor_generate_ir *ctx, struct ctx_decl_scope *scope,
388 const char *name, int levels, bool copy)
e98a2d6e 389{
4164020e
SM
390 return ctf_field_class_as_struct(
391 ctx_decl_scope_lookup_prefix_alias(ctx, scope, _PREFIX_STRUCT, name, levels, copy));
e98a2d6e
PP
392}
393
394/**
395 * Looks up a variant within a declaration scope.
396 *
397 * @param scope Declaration scope
398 * @param name Variant name
44c440bc
PP
399 * @param levels Number of levels to dig into (-1 means infinite)
400 * @param copy True to return a copy
401 * @returns Declaration (owned by caller if \p copy is true),
402 * or NULL if not found
e98a2d6e 403 */
4164020e
SM
404static struct ctf_field_class_variant *
405ctx_decl_scope_lookup_variant(struct ctf_visitor_generate_ir *ctx, struct ctx_decl_scope *scope,
406 const char *name, int levels, bool copy)
e98a2d6e 407{
4164020e
SM
408 return ctf_field_class_as_variant(
409 ctx_decl_scope_lookup_prefix_alias(ctx, scope, _PREFIX_VARIANT, name, levels, copy));
e98a2d6e
PP
410}
411
412/**
5cd6d0e5 413 * Registers a prefixed class alias within a declaration scope.
e98a2d6e
PP
414 *
415 * @param scope Declaration scope
416 * @param prefix Prefix character
417 * @param name Alias name (non-NULL)
5cd6d0e5 418 * @param decl Field class to register (copied)
e98a2d6e
PP
419 * @returns 0 if registration went okay, negative value otherwise
420 */
4164020e
SM
421static int ctx_decl_scope_register_prefix_alias(struct ctf_visitor_generate_ir *ctx,
422 struct ctx_decl_scope *scope, char prefix,
423 const char *name, struct ctf_field_class *decl)
e98a2d6e 424{
4164020e
SM
425 int ret = 0;
426 GQuark qname = 0;
427
428 BT_ASSERT(scope);
429 BT_ASSERT(name);
430 BT_ASSERT(decl);
431 qname = get_prefixed_named_quark(ctx, prefix, name);
432 if (!qname) {
433 ret = -ENOMEM;
434 goto end;
435 }
436
437 /* Make sure alias does not exist in local scope */
438 if (ctx_decl_scope_lookup_prefix_alias(ctx, scope, prefix, name, 1, false)) {
439 ret = -EEXIST;
440 goto end;
441 }
442
443 decl = ctf_field_class_copy(decl);
444 BT_ASSERT(decl);
445 g_hash_table_insert(scope->decl_map, GUINT_TO_POINTER(qname), decl);
e98a2d6e 446
44c440bc 447end:
4164020e 448 return ret;
e98a2d6e
PP
449}
450
451/**
5cd6d0e5 452 * Registers a class alias within a declaration scope.
e98a2d6e
PP
453 *
454 * @param scope Declaration scope
455 * @param name Alias name (non-NULL)
5cd6d0e5 456 * @param decl Field class to register (copied)
e98a2d6e
PP
457 * @returns 0 if registration went okay, negative value otherwise
458 */
4164020e
SM
459static int ctx_decl_scope_register_alias(struct ctf_visitor_generate_ir *ctx,
460 struct ctx_decl_scope *scope, const char *name,
461 struct ctf_field_class *decl)
e98a2d6e 462{
4164020e 463 return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_ALIAS, name, decl);
e98a2d6e
PP
464}
465
466/**
467 * Registers an enumeration declaration within a declaration scope.
468 *
469 * @param scope Declaration scope
470 * @param name Enumeration name (non-NULL)
5cd6d0e5 471 * @param decl Enumeration field class to register (copied)
e98a2d6e
PP
472 * @returns 0 if registration went okay, negative value otherwise
473 */
4164020e
SM
474static int ctx_decl_scope_register_enum(struct ctf_visitor_generate_ir *ctx,
475 struct ctx_decl_scope *scope, const char *name,
476 struct ctf_field_class_enum *decl)
e98a2d6e 477{
4164020e
SM
478 return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_ENUM, name,
479 &decl->base.base.base);
e98a2d6e
PP
480}
481
482/**
483 * Registers a structure declaration within a declaration scope.
484 *
485 * @param scope Declaration scope
486 * @param name Structure name (non-NULL)
5cd6d0e5 487 * @param decl Structure field class to register (copied)
e98a2d6e
PP
488 * @returns 0 if registration went okay, negative value otherwise
489 */
4164020e
SM
490static int ctx_decl_scope_register_struct(struct ctf_visitor_generate_ir *ctx,
491 struct ctx_decl_scope *scope, const char *name,
492 struct ctf_field_class_struct *decl)
e98a2d6e 493{
4164020e 494 return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_STRUCT, name, &decl->base);
e98a2d6e
PP
495}
496
497/**
498 * Registers a variant declaration within a declaration scope.
499 *
500 * @param scope Declaration scope
501 * @param name Variant name (non-NULL)
5cd6d0e5 502 * @param decl Variant field class to register
e98a2d6e
PP
503 * @returns 0 if registration went okay, negative value otherwise
504 */
4164020e
SM
505static int ctx_decl_scope_register_variant(struct ctf_visitor_generate_ir *ctx,
506 struct ctx_decl_scope *scope, const char *name,
507 struct ctf_field_class_variant *decl)
e98a2d6e 508{
4164020e 509 return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_VARIANT, name, &decl->base);
e98a2d6e
PP
510}
511
91fd6f6a
PP
512/**
513 * Destroys a visitor context.
514 *
515 * @param ctx Visitor context to destroy
516 */
4164020e 517static void ctx_destroy(struct ctf_visitor_generate_ir *ctx)
91fd6f6a 518{
4164020e 519 struct ctx_decl_scope *scope;
91fd6f6a 520
4164020e
SM
521 if (!ctx) {
522 goto end;
523 }
91fd6f6a 524
4164020e 525 scope = ctx->current_scope;
91fd6f6a 526
4164020e
SM
527 /*
528 * Destroy all scopes, from current one to the root scope.
529 */
530 while (scope) {
531 struct ctx_decl_scope *parent_scope = scope->parent_scope;
91fd6f6a 532
4164020e
SM
533 ctx_decl_scope_destroy(scope);
534 scope = parent_scope;
535 }
91fd6f6a 536
4164020e 537 bt_trace_class_put_ref(ctx->trace_class);
91fd6f6a 538
4164020e
SM
539 if (ctx->ctf_tc) {
540 ctf_trace_class_destroy(ctx->ctf_tc);
541 }
44c440bc 542
4164020e 543 g_free(ctx);
91fd6f6a
PP
544
545end:
4164020e 546 return;
91fd6f6a
PP
547}
548
e98a2d6e
PP
549/**
550 * Creates a new visitor context.
551 *
552 * @param trace Associated trace
e98a2d6e
PP
553 * @returns New visitor context, or NULL on error
554 */
4164020e
SM
555static struct ctf_visitor_generate_ir *
556ctx_create(const struct ctf_metadata_decoder_config *decoder_config)
e98a2d6e 557{
4164020e
SM
558 struct ctf_visitor_generate_ir *ctx = NULL;
559
560 BT_ASSERT(decoder_config);
561
562 ctx = g_new0(struct ctf_visitor_generate_ir, 1);
563 if (!ctx) {
564 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, decoder_config->log_level, decoder_config->self_comp,
565 "Failed to allocate one visitor context.");
566 goto error;
567 }
568
569 ctx->log_cfg.log_level = decoder_config->log_level;
570 ctx->log_cfg.self_comp = decoder_config->self_comp;
571 ctx->log_cfg.self_comp_class = decoder_config->self_comp_class;
572
573 if (decoder_config->self_comp) {
574 ctx->trace_class = bt_trace_class_create(decoder_config->self_comp);
575 if (!ctx->trace_class) {
576 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create empty trace class.");
577 goto error;
578 }
579 }
580
581 ctx->ctf_tc = ctf_trace_class_create();
582 if (!ctx->ctf_tc) {
583 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create CTF trace class.");
584 goto error;
585 }
586
587 /* Root declaration scope */
588 ctx->current_scope = ctx_decl_scope_create(ctx, NULL);
589 if (!ctx->current_scope) {
590 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
591 goto error;
592 }
593
594 ctx->decoder_config = *decoder_config;
595 goto end;
e98a2d6e
PP
596
597error:
4164020e
SM
598 ctx_destroy(ctx);
599 ctx = NULL;
44c440bc
PP
600
601end:
4164020e 602 return ctx;
e98a2d6e
PP
603}
604
e98a2d6e
PP
605/**
606 * Pushes a new declaration scope on top of a visitor context's
607 * declaration scope stack.
608 *
609 * @param ctx Visitor context
610 * @returns 0 on success, or a negative value on error
611 */
4164020e 612static int ctx_push_scope(struct ctf_visitor_generate_ir *ctx)
e98a2d6e 613{
4164020e
SM
614 int ret = 0;
615 struct ctx_decl_scope *new_scope;
e98a2d6e 616
4164020e
SM
617 BT_ASSERT(ctx);
618 new_scope = ctx_decl_scope_create(ctx, ctx->current_scope);
619 if (!new_scope) {
620 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
621 ret = -ENOMEM;
622 goto end;
623 }
e98a2d6e 624
4164020e 625 ctx->current_scope = new_scope;
e98a2d6e
PP
626
627end:
4164020e 628 return ret;
e98a2d6e
PP
629}
630
4164020e 631static void ctx_pop_scope(struct ctf_visitor_generate_ir *ctx)
e98a2d6e 632{
4164020e 633 struct ctx_decl_scope *parent_scope = NULL;
e98a2d6e 634
4164020e 635 BT_ASSERT(ctx);
e98a2d6e 636
4164020e
SM
637 if (!ctx->current_scope) {
638 goto end;
639 }
e98a2d6e 640
4164020e
SM
641 parent_scope = ctx->current_scope->parent_scope;
642 ctx_decl_scope_destroy(ctx->current_scope);
643 ctx->current_scope = parent_scope;
e98a2d6e
PP
644
645end:
4164020e 646 return;
e98a2d6e
PP
647}
648
4164020e
SM
649static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir *ctx,
650 struct ctf_node *ts_list,
651 struct ctf_field_class **decl);
e98a2d6e 652
4164020e 653static int is_unary_string(struct bt_list_head *head)
e98a2d6e 654{
4164020e
SM
655 int ret = TRUE;
656 struct ctf_node *node;
e98a2d6e 657
4164020e
SM
658 bt_list_for_each_entry (node, head, siblings) {
659 if (node->type != NODE_UNARY_EXPRESSION) {
660 ret = FALSE;
661 }
e98a2d6e 662
4164020e
SM
663 if (node->u.unary_expression.type != UNARY_STRING) {
664 ret = FALSE;
665 }
666 }
e98a2d6e 667
4164020e 668 return ret;
e98a2d6e
PP
669}
670
4164020e 671static const char *get_map_clock_name_value(struct bt_list_head *head)
e98a2d6e 672{
4164020e
SM
673 int i = 0;
674 struct ctf_node *node;
675 const char *name = NULL;
676
677 bt_list_for_each_entry (node, head, siblings) {
678 char *src_string;
679 int uexpr_type = node->u.unary_expression.type;
680 int uexpr_link = node->u.unary_expression.link;
681 int cond = node->type != NODE_UNARY_EXPRESSION || uexpr_type != UNARY_STRING ||
682 !((uexpr_link != UNARY_LINK_UNKNOWN) ^ (i == 0));
683 if (cond) {
684 goto error;
685 }
686
687 /* Needs to be chained with . */
688 switch (node->u.unary_expression.link) {
689 case UNARY_DOTLINK:
690 break;
691 case UNARY_ARROWLINK:
692 case UNARY_DOTDOTDOT:
693 goto error;
694 default:
695 break;
696 }
697
698 src_string = node->u.unary_expression.u.string;
699
700 switch (i) {
701 case 0:
702 if (strcmp("clock", src_string)) {
703 goto error;
704 }
705 break;
706 case 1:
707 name = src_string;
708 break;
709 case 2:
710 if (strcmp("value", src_string)) {
711 goto error;
712 }
713 break;
714 default:
715 /* Extra identifier, unknown */
716 goto error;
717 }
718
719 i++;
720 }
721
722 return name;
e98a2d6e
PP
723
724error:
4164020e 725 return NULL;
e98a2d6e
PP
726}
727
4164020e 728static int is_unary_unsigned(struct bt_list_head *head)
e98a2d6e 729{
4164020e
SM
730 int ret = TRUE;
731 struct ctf_node *node;
e98a2d6e 732
4164020e
SM
733 bt_list_for_each_entry (node, head, siblings) {
734 if (node->type != NODE_UNARY_EXPRESSION) {
735 ret = FALSE;
736 }
e98a2d6e 737
4164020e
SM
738 if (node->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
739 ret = FALSE;
740 }
741 }
e98a2d6e 742
4164020e 743 return ret;
e98a2d6e
PP
744}
745
4164020e
SM
746static int get_unary_unsigned(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *head,
747 uint64_t *value)
e98a2d6e 748{
4164020e
SM
749 int i = 0;
750 int ret = 0;
751 struct ctf_node *node;
752
753 *value = 0;
754
755 if (bt_list_empty(head)) {
756 ret = -1;
757 goto end;
758 }
759
760 bt_list_for_each_entry (node, head, siblings) {
761 int uexpr_type = node->u.unary_expression.type;
762 int uexpr_link = node->u.unary_expression.link;
763 int cond = node->type != NODE_UNARY_EXPRESSION || uexpr_type != UNARY_UNSIGNED_CONSTANT ||
764 uexpr_link != UNARY_LINK_UNKNOWN || i != 0;
765 if (cond) {
766 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Invalid constant unsigned integer.");
767 ret = -EINVAL;
768 goto end;
769 }
770
771 *value = node->u.unary_expression.u.unsigned_constant;
772 i++;
773 }
e98a2d6e
PP
774
775end:
4164020e 776 return ret;
e98a2d6e
PP
777}
778
4164020e 779static int is_unary_signed(struct bt_list_head *head)
e98a2d6e 780{
4164020e
SM
781 int ret = TRUE;
782 struct ctf_node *node;
e98a2d6e 783
4164020e
SM
784 bt_list_for_each_entry (node, head, siblings) {
785 if (node->type != NODE_UNARY_EXPRESSION) {
786 ret = FALSE;
787 }
e98a2d6e 788
4164020e
SM
789 if (node->u.unary_expression.type != UNARY_SIGNED_CONSTANT) {
790 ret = FALSE;
791 }
792 }
e98a2d6e 793
4164020e 794 return ret;
e98a2d6e
PP
795}
796
4164020e 797static int get_unary_signed(struct bt_list_head *head, int64_t *value)
e98a2d6e 798{
4164020e
SM
799 int i = 0;
800 int ret = 0;
801 struct ctf_node *node;
802
803 bt_list_for_each_entry (node, head, siblings) {
804 int uexpr_type = node->u.unary_expression.type;
805 int uexpr_link = node->u.unary_expression.link;
806 int cond = node->type != NODE_UNARY_EXPRESSION ||
807 (uexpr_type != UNARY_UNSIGNED_CONSTANT && uexpr_type != UNARY_SIGNED_CONSTANT) ||
808 uexpr_link != UNARY_LINK_UNKNOWN || i != 0;
809 if (cond) {
810 ret = -EINVAL;
811 goto end;
812 }
813
814 switch (uexpr_type) {
815 case UNARY_UNSIGNED_CONSTANT:
816 *value = (int64_t) node->u.unary_expression.u.unsigned_constant;
817 break;
818 case UNARY_SIGNED_CONSTANT:
819 *value = node->u.unary_expression.u.signed_constant;
820 break;
821 default:
822 ret = -EINVAL;
823 goto end;
824 }
825
826 i++;
827 }
e98a2d6e
PP
828
829end:
4164020e 830 return ret;
e98a2d6e
PP
831}
832
4164020e
SM
833static int get_unary_uuid(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *head,
834 bt_uuid_t uuid)
e98a2d6e 835{
4164020e 836 return ctf_ast_get_unary_uuid(head, uuid, ctx->log_cfg.log_level, ctx->log_cfg.self_comp);
e98a2d6e
PP
837}
838
4164020e 839static int get_boolean(struct ctf_visitor_generate_ir *ctx, struct ctf_node *unary_expr)
e98a2d6e 840{
4164020e
SM
841 int ret = 0;
842
843 if (unary_expr->type != NODE_UNARY_EXPRESSION) {
844 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr, "Expecting unary expression: node-type=%d",
845 unary_expr->type);
846 ret = -EINVAL;
847 goto end;
848 }
849
850 switch (unary_expr->u.unary_expression.type) {
851 case UNARY_UNSIGNED_CONSTANT:
852 ret = (unary_expr->u.unary_expression.u.unsigned_constant != 0);
853 break;
854 case UNARY_SIGNED_CONSTANT:
855 ret = (unary_expr->u.unary_expression.u.signed_constant != 0);
856 break;
857 case UNARY_STRING:
858 {
859 const char *str = unary_expr->u.unary_expression.u.string;
860
861 if (strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0) {
862 ret = TRUE;
863 } else if (strcmp(str, "false") == 0 || strcmp(str, "FALSE") == 0) {
864 ret = FALSE;
865 } else {
866 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr, "Unexpected boolean value: value=\"%s\"",
867 str);
868 ret = -EINVAL;
869 goto end;
870 }
871 break;
872 }
873 default:
874 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr,
875 "Unexpected unary expression type: node-type=%d",
876 unary_expr->u.unary_expression.type);
877 ret = -EINVAL;
878 goto end;
879 }
e98a2d6e
PP
880
881end:
4164020e 882 return ret;
e98a2d6e
PP
883}
884
4164020e
SM
885static enum ctf_byte_order byte_order_from_unary_expr(struct ctf_visitor_generate_ir *ctx,
886 struct ctf_node *unary_expr)
e98a2d6e 887{
4164020e
SM
888 const char *str;
889 enum ctf_byte_order bo = CTF_BYTE_ORDER_UNKNOWN;
890
891 if (unary_expr->u.unary_expression.type != UNARY_STRING) {
892 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
893 unary_expr, "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
894 goto end;
895 }
896
897 str = unary_expr->u.unary_expression.u.string;
898
899 if (strcmp(str, "be") == 0 || strcmp(str, "network") == 0) {
900 bo = CTF_BYTE_ORDER_BIG;
901 } else if (strcmp(str, "le") == 0) {
902 bo = CTF_BYTE_ORDER_LITTLE;
903 } else if (strcmp(str, "native") == 0) {
904 bo = CTF_BYTE_ORDER_DEFAULT;
905 } else {
906 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
907 unary_expr,
908 "Unexpected \"byte_order\" attribute value: "
909 "expecting `be`, `le`, `network`, or `native`: value=\"%s\"",
910 str);
911 goto end;
912 }
e98a2d6e
PP
913
914end:
4164020e 915 return bo;
e98a2d6e
PP
916}
917
4164020e
SM
918static enum ctf_byte_order get_real_byte_order(struct ctf_visitor_generate_ir *ctx,
919 struct ctf_node *uexpr)
e98a2d6e 920{
4164020e 921 enum ctf_byte_order bo = byte_order_from_unary_expr(ctx, uexpr);
e98a2d6e 922
4164020e
SM
923 if (bo == CTF_BYTE_ORDER_DEFAULT) {
924 bo = ctx->ctf_tc->default_byte_order;
925 }
e98a2d6e 926
4164020e 927 return bo;
e98a2d6e
PP
928}
929
4164020e 930static int is_align_valid(uint64_t align)
e98a2d6e 931{
4164020e 932 return (align != 0) && !(align & (align - UINT64_C(1)));
e98a2d6e
PP
933}
934
4164020e
SM
935static int get_class_specifier_name(struct ctf_visitor_generate_ir *ctx,
936 struct ctf_node *cls_specifier, GString *str)
e98a2d6e 937{
4164020e
SM
938 int ret = 0;
939
940 if (cls_specifier->type != NODE_TYPE_SPECIFIER) {
941 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier, "Unexpected node type: node-type=%d",
942 cls_specifier->type);
943 ret = -EINVAL;
944 goto end;
945 }
946
947 switch (cls_specifier->u.field_class_specifier.type) {
948 case TYPESPEC_VOID:
949 g_string_append(str, "void");
950 break;
951 case TYPESPEC_CHAR:
952 g_string_append(str, "char");
953 break;
954 case TYPESPEC_SHORT:
955 g_string_append(str, "short");
956 break;
957 case TYPESPEC_INT:
958 g_string_append(str, "int");
959 break;
960 case TYPESPEC_LONG:
961 g_string_append(str, "long");
962 break;
963 case TYPESPEC_FLOAT:
964 g_string_append(str, "float");
965 break;
966 case TYPESPEC_DOUBLE:
967 g_string_append(str, "double");
968 break;
969 case TYPESPEC_SIGNED:
970 g_string_append(str, "signed");
971 break;
972 case TYPESPEC_UNSIGNED:
973 g_string_append(str, "unsigned");
974 break;
975 case TYPESPEC_BOOL:
976 g_string_append(str, "bool");
977 break;
978 case TYPESPEC_COMPLEX:
979 g_string_append(str, "_Complex");
980 break;
981 case TYPESPEC_IMAGINARY:
982 g_string_append(str, "_Imaginary");
983 break;
984 case TYPESPEC_CONST:
985 g_string_append(str, "const");
986 break;
987 case TYPESPEC_ID_TYPE:
988 if (cls_specifier->u.field_class_specifier.id_type) {
989 g_string_append(str, cls_specifier->u.field_class_specifier.id_type);
990 }
991 break;
992 case TYPESPEC_STRUCT:
993 {
994 struct ctf_node *node = cls_specifier->u.field_class_specifier.node;
995
996 if (!node->u._struct.name) {
997 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unexpected empty structure field class name.");
998 ret = -EINVAL;
999 goto end;
1000 }
1001
1002 g_string_append(str, "struct ");
1003 g_string_append(str, node->u._struct.name);
1004 break;
1005 }
1006 case TYPESPEC_VARIANT:
1007 {
1008 struct ctf_node *node = cls_specifier->u.field_class_specifier.node;
1009
1010 if (!node->u.variant.name) {
1011 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unexpected empty variant field class name.");
1012 ret = -EINVAL;
1013 goto end;
1014 }
1015
1016 g_string_append(str, "variant ");
1017 g_string_append(str, node->u.variant.name);
1018 break;
1019 }
1020 case TYPESPEC_ENUM:
1021 {
1022 struct ctf_node *node = cls_specifier->u.field_class_specifier.node;
1023
1024 if (!node->u._enum.enum_id) {
1025 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1026 node, "Unexpected empty enumeration field class (`enum`) name.");
1027 ret = -EINVAL;
1028 goto end;
1029 }
1030
1031 g_string_append(str, "enum ");
1032 g_string_append(str, node->u._enum.enum_id);
1033 break;
1034 }
1035 case TYPESPEC_FLOATING_POINT:
1036 case TYPESPEC_INTEGER:
1037 case TYPESPEC_STRING:
1038 default:
1039 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier->u.field_class_specifier.node,
1040 "Unexpected field class specifier type: %d",
1041 cls_specifier->u.field_class_specifier.type);
1042 ret = -EINVAL;
1043 goto end;
1044 }
e98a2d6e
PP
1045
1046end:
4164020e 1047 return ret;
e98a2d6e
PP
1048}
1049
4164020e
SM
1050static int get_class_specifier_list_name(struct ctf_visitor_generate_ir *ctx,
1051 struct ctf_node *cls_specifier_list, GString *str)
e98a2d6e 1052{
4164020e
SM
1053 int ret = 0;
1054 struct ctf_node *iter;
1055 int alias_item_nr = 0;
1056 struct bt_list_head *head = &cls_specifier_list->u.field_class_specifier_list.head;
1057
1058 bt_list_for_each_entry (iter, head, siblings) {
1059 if (alias_item_nr != 0) {
1060 g_string_append(str, " ");
1061 }
1062
1063 alias_item_nr++;
1064 ret = get_class_specifier_name(ctx, iter, str);
1065 if (ret) {
1066 goto end;
1067 }
1068 }
e98a2d6e
PP
1069
1070end:
4164020e 1071 return ret;
e98a2d6e
PP
1072}
1073
4164020e
SM
1074static GQuark create_class_alias_identifier(struct ctf_visitor_generate_ir *ctx,
1075 struct ctf_node *cls_specifier_list,
1076 struct ctf_node *node_field_class_declarator)
e98a2d6e 1077{
4164020e
SM
1078 int ret;
1079 char *str_c;
1080 GString *str;
1081 GQuark qalias = 0;
1082 struct ctf_node *iter;
1083 struct bt_list_head *pointers = &node_field_class_declarator->u.field_class_declarator.pointers;
1084
1085 str = g_string_new("");
1086 ret = get_class_specifier_list_name(ctx, cls_specifier_list, str);
1087 if (ret) {
1088 g_string_free(str, TRUE);
1089 goto end;
1090 }
1091
1092 bt_list_for_each_entry (iter, pointers, siblings) {
1093 g_string_append(str, " *");
1094
1095 if (iter->u.pointer.const_qualifier) {
1096 g_string_append(str, " const");
1097 }
1098 }
1099
1100 str_c = g_string_free(str, FALSE);
1101 qalias = g_quark_from_string(str_c);
1102 g_free(str_c);
e98a2d6e
PP
1103
1104end:
4164020e 1105 return qalias;
e98a2d6e
PP
1106}
1107
4164020e
SM
1108static int visit_field_class_declarator(struct ctf_visitor_generate_ir *ctx,
1109 struct ctf_node *cls_specifier_list, GQuark *field_name,
1110 struct ctf_node *node_field_class_declarator,
1111 struct ctf_field_class **field_decl,
1112 struct ctf_field_class *nested_decl)
e98a2d6e 1113{
4164020e
SM
1114 /*
1115 * During this whole function, nested_decl is always OURS,
1116 * whereas field_decl is an output which we create, but
1117 * belongs to the caller (it is moved).
1118 */
1119 int ret = 0;
1120 *field_decl = NULL;
1121
1122 /* Validate field class declarator node */
1123 if (node_field_class_declarator) {
1124 if (node_field_class_declarator->u.field_class_declarator.type == TYPEDEC_UNKNOWN) {
1125 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1126 node_field_class_declarator, "Unexpected field class declarator type: type=%d",
1127 node_field_class_declarator->u.field_class_declarator.type);
1128 ret = -EINVAL;
1129 goto error;
1130 }
1131
1132 /* TODO: GCC bitfields not supported yet */
1133 if (node_field_class_declarator->u.field_class_declarator.bitfield_len != NULL) {
1134 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1135 "GCC bitfields are not supported as of this version.");
1136 ret = -EPERM;
1137 goto error;
1138 }
1139 }
1140
1141 /* Find the right nested declaration if not provided */
1142 if (!nested_decl) {
1143 struct bt_list_head *pointers =
1144 &node_field_class_declarator->u.field_class_declarator.pointers;
1145
1146 if (node_field_class_declarator && !bt_list_empty(pointers)) {
1147 GQuark qalias;
1148
1149 /*
1150 * If we have a pointer declarator, it HAS to
5cd6d0e5
PP
1151 * be present in the field class aliases (else
1152 * fail).
4164020e
SM
1153 */
1154 qalias =
1155 create_class_alias_identifier(ctx, cls_specifier_list, node_field_class_declarator);
1156 nested_decl = ctx_decl_scope_lookup_alias(ctx, ctx->current_scope,
1157 g_quark_to_string(qalias), -1, true);
1158 if (!nested_decl) {
1159 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1160 "Cannot find class alias: name=\"%s\"",
1161 g_quark_to_string(qalias));
1162 ret = -EINVAL;
1163 goto error;
1164 }
1165
1166 if (nested_decl->type == CTF_FIELD_CLASS_TYPE_INT) {
1167 /* Pointer: force integer's base to 16 */
1168 struct ctf_field_class_int *int_fc = ctf_field_class_as_int(nested_decl);
1169
1170 int_fc->disp_base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
1171 }
1172 } else {
1173 ret = visit_field_class_specifier_list(ctx, cls_specifier_list, &nested_decl);
1174 if (ret) {
1175 BT_ASSERT(!nested_decl);
1176 goto error;
1177 }
1178 }
1179 }
1180
1181 BT_ASSERT(nested_decl);
1182
1183 if (!node_field_class_declarator) {
1184 *field_decl = nested_decl;
1185 nested_decl = NULL;
1186 goto end;
1187 }
1188
1189 if (node_field_class_declarator->u.field_class_declarator.type == TYPEDEC_ID) {
1190 if (node_field_class_declarator->u.field_class_declarator.u.id) {
1191 const char *id = node_field_class_declarator->u.field_class_declarator.u.id;
1192
1193 *field_name = g_quark_from_string(id);
1194 } else {
1195 *field_name = 0;
1196 }
1197
1198 *field_decl = nested_decl;
1199 nested_decl = NULL;
1200 goto end;
1201 } else {
1202 struct ctf_node *first;
1203 struct ctf_field_class *decl = NULL;
1204 struct ctf_field_class *outer_field_decl = NULL;
1205 struct bt_list_head *length =
1206 &node_field_class_declarator->u.field_class_declarator.u.nested.length;
1207
1208 /* Create array/sequence, pass nested_decl as child */
1209 if (bt_list_empty(length)) {
1210 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1211 "Expecting length field reference or value.");
1212 ret = -EINVAL;
1213 goto error;
1214 }
1215
1216 first = _BT_LIST_FIRST_ENTRY(length, struct ctf_node, siblings);
1217 if (first->type != NODE_UNARY_EXPRESSION) {
1218 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first, "Unexpected node type: node-type=%d",
1219 first->type);
1220 ret = -EINVAL;
1221 goto error;
1222 }
1223
1224 switch (first->u.unary_expression.type) {
1225 case UNARY_UNSIGNED_CONSTANT:
1226 {
1227 struct ctf_field_class_array *array_decl = NULL;
1228
1229 array_decl = ctf_field_class_array_create();
1230 BT_ASSERT(array_decl);
1231 array_decl->length = first->u.unary_expression.u.unsigned_constant;
1232 array_decl->base.elem_fc = nested_decl;
1233 nested_decl = NULL;
1234 decl = &array_decl->base.base;
1235 break;
1236 }
1237 case UNARY_STRING:
1238 {
1239 /* Lookup unsigned integer definition, create seq. */
1240 struct ctf_field_class_sequence *seq_decl = NULL;
1241 char *length_name = ctf_ast_concatenate_unary_strings(length);
1242
1243 if (!length_name) {
1244 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1245 "Cannot concatenate unary strings.");
1246 ret = -EINVAL;
1247 goto error;
1248 }
1249
1250 if (strncmp(length_name, "env.", 4) == 0) {
1251 /* This is, in fact, an array */
1252 const char *env_entry_name = &length_name[4];
1253 struct ctf_trace_class_env_entry *env_entry =
1254 ctf_trace_class_borrow_env_entry_by_name(ctx->ctf_tc, env_entry_name);
1255 struct ctf_field_class_array *array_decl;
1256
1257 if (!env_entry) {
1258 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1259 "Cannot find environment entry: "
1260 "name=\"%s\"",
1261 env_entry_name);
1262 ret = -EINVAL;
1263 goto error;
1264 }
1265
1266 if (env_entry->type != CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT) {
1267 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1268 "Wrong environment entry type "
1269 "(expecting integer): "
1270 "name=\"%s\"",
1271 env_entry_name);
1272 ret = -EINVAL;
1273 goto error;
1274 }
1275
1276 if (env_entry->value.i < 0) {
1277 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1278 "Invalid, negative array length: "
1279 "env-entry-name=\"%s\", "
1280 "value=%" PRId64,
1281 env_entry_name, env_entry->value.i);
1282 ret = -EINVAL;
1283 goto error;
1284 }
1285
1286 array_decl = ctf_field_class_array_create();
1287 BT_ASSERT(array_decl);
1288 array_decl->length = (uint64_t) env_entry->value.i;
1289 array_decl->base.elem_fc = nested_decl;
1290 nested_decl = NULL;
1291 decl = &array_decl->base.base;
1292 } else {
1293 seq_decl = ctf_field_class_sequence_create();
1294 BT_ASSERT(seq_decl);
1295 seq_decl->base.elem_fc = nested_decl;
1296 nested_decl = NULL;
1297 g_string_assign(seq_decl->length_ref, length_name);
1298 decl = &seq_decl->base.base;
1299 }
1300
1301 g_free(length_name);
1302 break;
1303 }
1304 default:
1305 ret = -EINVAL;
1306 goto error;
1307 }
1308
1309 BT_ASSERT(!nested_decl);
1310 BT_ASSERT(decl);
1311 BT_ASSERT(!*field_decl);
1312
1313 /*
1314 * At this point, we found the next nested declaration.
1315 * We currently own this (and lost the ownership of
1316 * nested_decl in the meantime). Pass this next
1317 * nested declaration as the content of the outer
1318 * container, MOVING its ownership.
1319 */
1320 ret = visit_field_class_declarator(
1321 ctx, cls_specifier_list, field_name,
1322 node_field_class_declarator->u.field_class_declarator.u.nested.field_class_declarator,
1323 &outer_field_decl, decl);
1324 decl = NULL;
1325 if (ret) {
1326 BT_ASSERT(!outer_field_decl);
1327 ret = -EINVAL;
1328 goto error;
1329 }
1330
1331 BT_ASSERT(outer_field_decl);
1332 *field_decl = outer_field_decl;
1333 outer_field_decl = NULL;
1334 }
1335
1336 BT_ASSERT(*field_decl);
1337 goto end;
e98a2d6e
PP
1338
1339error:
4164020e
SM
1340 ctf_field_class_destroy(*field_decl);
1341 *field_decl = NULL;
e98a2d6e 1342
4164020e
SM
1343 if (ret >= 0) {
1344 ret = -1;
1345 }
44c440bc
PP
1346
1347end:
4164020e
SM
1348 ctf_field_class_destroy(nested_decl);
1349 nested_decl = NULL;
1350 return ret;
e98a2d6e
PP
1351}
1352
4164020e
SM
1353static int visit_struct_decl_field(struct ctf_visitor_generate_ir *ctx,
1354 struct ctf_field_class_struct *struct_decl,
1355 struct ctf_node *cls_specifier_list,
1356 struct bt_list_head *field_class_declarators)
e98a2d6e 1357{
4164020e
SM
1358 int ret = 0;
1359 struct ctf_node *iter;
1360 struct ctf_field_class *field_decl = NULL;
1361
1362 bt_list_for_each_entry (iter, field_class_declarators, siblings) {
1363 field_decl = NULL;
1364 GQuark qfield_name;
1365 const char *field_name;
1366
1367 ret = visit_field_class_declarator(ctx, cls_specifier_list, &qfield_name, iter, &field_decl,
1368 NULL);
1369 if (ret) {
1370 BT_ASSERT(!field_decl);
1371 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
1372 "Cannot visit field class declarator: ret=%d", ret);
1373 goto error;
1374 }
1375
1376 BT_ASSERT(field_decl);
1377 field_name = g_quark_to_string(qfield_name);
1378
1379 /* Check if field with same name already exists */
1380 if (ctf_field_class_struct_borrow_member_by_name(struct_decl, field_name)) {
1381 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
1382 "Duplicate field in structure field class: "
1383 "field-name=\"%s\"",
1384 field_name);
1385 ret = -EINVAL;
1386 goto error;
1387 }
1388
1389 /* Add field to structure */
1390 ctf_field_class_struct_append_member(struct_decl, field_name, field_decl);
1391 field_decl = NULL;
1392 }
1393
1394 return 0;
e98a2d6e
PP
1395
1396error:
4164020e
SM
1397 ctf_field_class_destroy(field_decl);
1398 field_decl = NULL;
1399 return ret;
e98a2d6e
PP
1400}
1401
4164020e
SM
1402static int visit_variant_decl_field(struct ctf_visitor_generate_ir *ctx,
1403 struct ctf_field_class_variant *variant_decl,
1404 struct ctf_node *cls_specifier_list,
1405 struct bt_list_head *field_class_declarators)
e98a2d6e 1406{
4164020e
SM
1407 int ret = 0;
1408 struct ctf_node *iter;
1409 struct ctf_field_class *field_decl = NULL;
1410
1411 bt_list_for_each_entry (iter, field_class_declarators, siblings) {
1412 field_decl = NULL;
1413 GQuark qfield_name;
1414 const char *field_name;
1415
1416 ret = visit_field_class_declarator(ctx, cls_specifier_list, &qfield_name, iter, &field_decl,
1417 NULL);
1418 if (ret) {
1419 BT_ASSERT(!field_decl);
1420 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
1421 "Cannot visit field class declarator: ret=%d", ret);
1422 goto error;
1423 }
1424
1425 BT_ASSERT(field_decl);
1426 field_name = g_quark_to_string(qfield_name);
1427
1428 /* Check if field with same name already exists */
1429 if (ctf_field_class_variant_borrow_option_by_name(variant_decl, field_name)) {
1430 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
1431 "Duplicate field in variant field class: "
1432 "field-name=\"%s\"",
1433 field_name);
1434 ret = -EINVAL;
1435 goto error;
1436 }
1437
1438 /* Add field to structure */
1439 ctf_field_class_variant_append_option(variant_decl, field_name, field_decl);
1440 field_decl = NULL;
1441 }
1442
1443 return 0;
e98a2d6e
PP
1444
1445error:
4164020e
SM
1446 ctf_field_class_destroy(field_decl);
1447 field_decl = NULL;
1448 return ret;
e98a2d6e
PP
1449}
1450
4164020e
SM
1451static int visit_field_class_def(struct ctf_visitor_generate_ir *ctx,
1452 struct ctf_node *cls_specifier_list,
1453 struct bt_list_head *field_class_declarators)
e98a2d6e 1454{
4164020e
SM
1455 int ret = 0;
1456 GQuark qidentifier;
1457 struct ctf_node *iter;
1458 struct ctf_field_class *class_decl = NULL;
1459
1460 bt_list_for_each_entry (iter, field_class_declarators, siblings) {
1461 ret = visit_field_class_declarator(ctx, cls_specifier_list, &qidentifier, iter, &class_decl,
1462 NULL);
1463 if (ret) {
1464 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit field class declarator: ret=%d",
1465 ret);
1466 ret = -EINVAL;
1467 goto end;
1468 }
1469
1470 /* Do not allow field class def and alias of untagged variants */
1471 if (class_decl->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
1472 struct ctf_field_class_variant *var_fc = ctf_field_class_as_variant(class_decl);
1473
1474 if (var_fc->tag_path.path->len == 0) {
1475 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1476 iter, "Type definition of untagged variant field class is not allowed.");
1477 ret = -EPERM;
1478 goto end;
1479 }
1480 }
1481
1482 ret = ctx_decl_scope_register_alias(ctx, ctx->current_scope, g_quark_to_string(qidentifier),
1483 class_decl);
1484 if (ret) {
1485 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot register field class alias: name=\"%s\"",
1486 g_quark_to_string(qidentifier));
1487 goto end;
1488 }
1489 }
e98a2d6e
PP
1490
1491end:
4164020e
SM
1492 ctf_field_class_destroy(class_decl);
1493 class_decl = NULL;
1494 return ret;
e98a2d6e
PP
1495}
1496
4164020e
SM
1497static int visit_field_class_alias(struct ctf_visitor_generate_ir *ctx, struct ctf_node *target,
1498 struct ctf_node *alias)
e98a2d6e 1499{
4164020e
SM
1500 int ret = 0;
1501 GQuark qalias;
1502 struct ctf_node *node;
1503 GQuark qdummy_field_name;
1504 struct ctf_field_class *class_decl = NULL;
1505
1506 /* Create target field class */
1507 if (bt_list_empty(&target->u.field_class_alias_target.field_class_declarators)) {
1508 node = NULL;
1509 } else {
1510 node = _BT_LIST_FIRST_ENTRY(&target->u.field_class_alias_target.field_class_declarators,
1511 struct ctf_node, siblings);
1512 }
1513
1514 ret = visit_field_class_declarator(
1515 ctx, target->u.field_class_alias_target.field_class_specifier_list, &qdummy_field_name,
1516 node, &class_decl, NULL);
1517 if (ret) {
1518 BT_ASSERT(!class_decl);
1519 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot visit field class declarator: ret=%d", ret);
1520 goto end;
1521 }
1522
1523 /* Do not allow field class def and alias of untagged variants */
1524 if (class_decl->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
1525 struct ctf_field_class_variant *var_fc = ctf_field_class_as_variant(class_decl);
1526
1527 if (var_fc->tag_path.path->len == 0) {
1528 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1529 target, "Type definition of untagged variant field class is not allowed.");
1530 ret = -EPERM;
1531 goto end;
1532 }
1533 }
1534
1535 /*
1536 * The semantic validator does not check whether the target is
1537 * abstract or not (if it has an identifier). Check it here.
1538 */
1539 if (qdummy_field_name != 0) {
1540 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target, "Expecting empty identifier: id=\"%s\"",
1541 g_quark_to_string(qdummy_field_name));
1542 ret = -EINVAL;
1543 goto end;
1544 }
1545
1546 /* Create alias identifier */
1547 node = _BT_LIST_FIRST_ENTRY(&alias->u.field_class_alias_name.field_class_declarators,
1548 struct ctf_node, siblings);
1549 qalias = create_class_alias_identifier(
1550 ctx, alias->u.field_class_alias_name.field_class_specifier_list, node);
1551 ret = ctx_decl_scope_register_alias(ctx, ctx->current_scope, g_quark_to_string(qalias),
1552 class_decl);
1553 if (ret) {
1554 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot register class alias: name=\"%s\"",
1555 g_quark_to_string(qalias));
1556 goto end;
1557 }
e98a2d6e
PP
1558
1559end:
4164020e
SM
1560 ctf_field_class_destroy(class_decl);
1561 class_decl = NULL;
1562 return ret;
e98a2d6e
PP
1563}
1564
4164020e
SM
1565static int visit_struct_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *entry_node,
1566 struct ctf_field_class_struct *struct_decl)
e98a2d6e 1567{
4164020e
SM
1568 int ret = 0;
1569
1570 switch (entry_node->type) {
1571 case NODE_TYPEDEF:
1572 ret = visit_field_class_def(ctx, entry_node->u.field_class_def.field_class_specifier_list,
1573 &entry_node->u.field_class_def.field_class_declarators);
1574 if (ret) {
1575 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1576 entry_node, "Cannot add field class found in structure field class: ret=%d", ret);
1577 goto end;
1578 }
1579 break;
1580 case NODE_TYPEALIAS:
1581 ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target,
1582 entry_node->u.field_class_alias.alias);
1583 if (ret) {
1584 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1585 entry_node, "Cannot add field class alias found in structure field class: ret=%d",
1586 ret);
1587 goto end;
1588 }
1589 break;
1590 case NODE_STRUCT_OR_VARIANT_DECLARATION:
1591 /* Field */
1592 ret = visit_struct_decl_field(
1593 ctx, struct_decl,
1594 entry_node->u.struct_or_variant_declaration.field_class_specifier_list,
1595 &entry_node->u.struct_or_variant_declaration.field_class_declarators);
1596 if (ret) {
1597 goto end;
1598 }
1599 break;
1600 default:
1601 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Unexpected node type: node-type=%d",
1602 entry_node->type);
1603 ret = -EINVAL;
1604 goto end;
1605 }
e98a2d6e
PP
1606
1607end:
4164020e 1608 return ret;
e98a2d6e
PP
1609}
1610
4164020e
SM
1611static int visit_variant_decl_entry(struct ctf_visitor_generate_ir *ctx,
1612 struct ctf_node *entry_node,
1613 struct ctf_field_class_variant *variant_decl)
e98a2d6e 1614{
4164020e
SM
1615 int ret = 0;
1616
1617 switch (entry_node->type) {
1618 case NODE_TYPEDEF:
1619 ret = visit_field_class_def(ctx, entry_node->u.field_class_def.field_class_specifier_list,
1620 &entry_node->u.field_class_def.field_class_declarators);
1621 if (ret) {
1622 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1623 entry_node, "Cannot add field class found in variant field class: ret=%d", ret);
1624 goto end;
1625 }
1626 break;
1627 case NODE_TYPEALIAS:
1628 ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target,
1629 entry_node->u.field_class_alias.alias);
1630 if (ret) {
1631 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1632 entry_node, "Cannot add field class alias found in variant field class: ret=%d",
1633 ret);
1634 goto end;
1635 }
1636 break;
1637 case NODE_STRUCT_OR_VARIANT_DECLARATION:
1638 /* Field */
1639 ret = visit_variant_decl_field(
1640 ctx, variant_decl,
1641 entry_node->u.struct_or_variant_declaration.field_class_specifier_list,
1642 &entry_node->u.struct_or_variant_declaration.field_class_declarators);
1643 if (ret) {
1644 goto end;
1645 }
1646 break;
1647 default:
1648 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Unexpected node type: node-type=%d",
1649 entry_node->type);
1650 ret = -EINVAL;
1651 goto end;
1652 }
e98a2d6e
PP
1653
1654end:
4164020e 1655 return ret;
e98a2d6e
PP
1656}
1657
4164020e
SM
1658static int visit_struct_decl(struct ctf_visitor_generate_ir *ctx, const char *name,
1659 struct bt_list_head *decl_list, int has_body,
1660 struct bt_list_head *min_align,
1661 struct ctf_field_class_struct **struct_decl)
e98a2d6e 1662{
4164020e
SM
1663 int ret = 0;
1664
1665 BT_ASSERT(struct_decl);
1666 *struct_decl = NULL;
1667
1668 /* For named struct (without body), lookup in declaration scope */
1669 if (!has_body) {
1670 if (!name) {
1671 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1672 "Bodyless structure field class: missing name.");
1673 ret = -EPERM;
1674 goto error;
1675 }
1676
1677 *struct_decl = ctx_decl_scope_lookup_struct(ctx, ctx->current_scope, name, -1, true);
1678 if (!*struct_decl) {
1679 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1680 "Cannot find structure field class: name=\"struct %s\"", name);
1681 ret = -EINVAL;
1682 goto error;
1683 }
1684 } else {
1685 struct ctf_node *entry_node;
1686 uint64_t min_align_value = 0;
1687
1688 if (name) {
1689 if (ctx_decl_scope_lookup_struct(ctx, ctx->current_scope, name, 1, false)) {
1690 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1691 "Structure field class already declared in local scope: "
1692 "name=\"struct %s\"",
1693 name);
1694 ret = -EINVAL;
1695 goto error;
1696 }
1697 }
1698
1699 if (!bt_list_empty(min_align)) {
1700 ret = get_unary_unsigned(ctx, min_align, &min_align_value);
1701 if (ret) {
1702 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1703 "Unexpected unary expression for structure field class's `align` attribute: "
1704 "ret=%d",
1705 ret);
1706 goto error;
1707 }
1708 }
1709
1710 *struct_decl = ctf_field_class_struct_create();
1711 BT_ASSERT(*struct_decl);
1712
1713 if (min_align_value != 0) {
1714 (*struct_decl)->base.alignment = min_align_value;
1715 }
1716
1717 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1718
1719 bt_list_for_each_entry (entry_node, decl_list, siblings) {
1720 ret = visit_struct_decl_entry(ctx, entry_node, *struct_decl);
1721 if (ret) {
1722 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
1723 "Cannot visit structure field class entry: "
1724 "ret=%d",
1725 ret);
1726 ctx_pop_scope(ctx);
1727 goto error;
1728 }
1729 }
1730
1731 ctx_pop_scope(ctx);
1732
1733 if (name) {
1734 ret = ctx_decl_scope_register_struct(ctx, ctx->current_scope, name, *struct_decl);
1735 if (ret) {
1736 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1737 "Cannot register structure field class in declaration scope: "
1738 "name=\"struct %s\", ret=%d",
1739 name, ret);
1740 goto error;
1741 }
1742 }
1743 }
1744
1745 return 0;
e98a2d6e
PP
1746
1747error:
4164020e
SM
1748 ctf_field_class_destroy(&(*struct_decl)->base);
1749 *struct_decl = NULL;
1750 return ret;
e98a2d6e
PP
1751}
1752
4164020e
SM
1753static int visit_variant_decl(struct ctf_visitor_generate_ir *ctx, const char *name,
1754 const char *tag, struct bt_list_head *decl_list, int has_body,
1755 struct ctf_field_class_variant **variant_decl)
e98a2d6e 1756{
4164020e
SM
1757 int ret = 0;
1758 struct ctf_field_class_variant *untagged_variant_decl = NULL;
1759
1760 BT_ASSERT(variant_decl);
1761 *variant_decl = NULL;
1762
1763 /* For named variant (without body), lookup in declaration scope */
1764 if (!has_body) {
1765 if (!name) {
1766 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name.");
1767 ret = -EPERM;
1768 goto error;
1769 }
1770
1771 untagged_variant_decl =
1772 ctx_decl_scope_lookup_variant(ctx, ctx->current_scope, name, -1, true);
1773 if (!untagged_variant_decl) {
1774 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1775 "Cannot find variant field class: name=\"variant %s\"", name);
1776 ret = -EINVAL;
1777 goto error;
1778 }
1779 } else {
1780 struct ctf_node *entry_node;
1781
1782 if (name) {
1783 if (ctx_decl_scope_lookup_variant(ctx, ctx->current_scope, name, 1, false)) {
1784 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1785 "Variant field class already declared in local scope: "
1786 "name=\"variant %s\"",
1787 name);
1788 ret = -EINVAL;
1789 goto error;
1790 }
1791 }
1792
1793 untagged_variant_decl = ctf_field_class_variant_create();
1794 BT_ASSERT(untagged_variant_decl);
1795 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1796
1797 bt_list_for_each_entry (entry_node, decl_list, siblings) {
1798 ret = visit_variant_decl_entry(ctx, entry_node, untagged_variant_decl);
1799 if (ret) {
1800 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
1801 "Cannot visit variant field class entry: "
1802 "ret=%d",
1803 ret);
1804 ctx_pop_scope(ctx);
1805 goto error;
1806 }
1807 }
1808
1809 ctx_pop_scope(ctx);
1810
1811 if (name) {
1812 ret = ctx_decl_scope_register_variant(ctx, ctx->current_scope, name,
1813 untagged_variant_decl);
1814 if (ret) {
1815 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1816 "Cannot register variant field class in declaration scope: "
1817 "name=\"variant %s\", ret=%d",
1818 name, ret);
1819 goto error;
1820 }
1821 }
1822 }
1823
1824 /*
1825 * If tagged, create tagged variant and return; otherwise
1826 * return untagged variant.
1827 */
1828 if (!tag) {
1829 *variant_decl = untagged_variant_decl;
1830 untagged_variant_decl = NULL;
1831 } else {
1832 /*
1833 * At this point, we have a fresh untagged variant; nobody
1834 * else owns it. Set its tag now.
1835 */
1836 g_string_assign(untagged_variant_decl->tag_ref, tag);
1837 *variant_decl = untagged_variant_decl;
1838 untagged_variant_decl = NULL;
1839 }
1840
1841 BT_ASSERT(!untagged_variant_decl);
1842 BT_ASSERT(*variant_decl);
1843 return 0;
e98a2d6e
PP
1844
1845error:
4164020e
SM
1846 ctf_field_class_destroy(&untagged_variant_decl->base);
1847 untagged_variant_decl = NULL;
1848 ctf_field_class_destroy(&(*variant_decl)->base);
1849 *variant_decl = NULL;
1850 return ret;
e98a2d6e
PP
1851}
1852
4164020e
SM
1853struct uori
1854{
1855 bool is_signed;
1856 union
1857 {
1858 uint64_t u;
1859 uint64_t i;
1860 } value;
44c440bc
PP
1861};
1862
4164020e
SM
1863static int visit_enum_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *enumerator,
1864 struct ctf_field_class_enum *enum_decl, struct uori *last)
e98a2d6e 1865{
4164020e
SM
1866 int ret = 0;
1867 int nr_vals = 0;
1868 struct ctf_node *iter;
1869 struct uori start = {
1870 .is_signed = false,
1871 .value =
1872 {
1873 .u = 0,
1874 },
1875 };
1876 struct uori end = {
1877 .is_signed = false,
1878 .value =
1879 {
1880 .u = 0,
1881 },
1882 };
1883 const char *label = enumerator->u.enumerator.id;
1884 struct bt_list_head *values = &enumerator->u.enumerator.values;
1885
1886 bt_list_for_each_entry (iter, values, siblings) {
1887 struct uori *target;
1888
1889 if (iter->type != NODE_UNARY_EXPRESSION) {
1890 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
1891 "Wrong expression for enumeration field class label: "
1892 "node-type=%d, label=\"%s\"",
1893 iter->type, label);
1894 ret = -EINVAL;
1895 goto error;
1896 }
1897
1898 if (nr_vals == 0) {
1899 target = &start;
1900 } else {
1901 target = &end;
1902 }
1903
1904 switch (iter->u.unary_expression.type) {
1905 case UNARY_SIGNED_CONSTANT:
1906 target->is_signed = true;
1907 target->value.i = iter->u.unary_expression.u.signed_constant;
1908 break;
1909 case UNARY_UNSIGNED_CONSTANT:
1910 target->is_signed = false;
1911 target->value.u = iter->u.unary_expression.u.unsigned_constant;
1912 break;
1913 default:
1914 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
1915 "Invalid enumeration field class entry: "
1916 "expecting constant signed or unsigned integer: "
1917 "node-type=%d, label=\"%s\"",
1918 iter->u.unary_expression.type, label);
1919 ret = -EINVAL;
1920 goto error;
1921 }
1922
1923 if (nr_vals > 1) {
1924 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
1925 iter, "Invalid enumeration field class entry: label=\"%s\"", label);
1926 ret = -EINVAL;
1927 goto error;
1928 }
1929
1930 nr_vals++;
1931 }
1932
1933 if (nr_vals == 0) {
1934 start = *last;
1935 }
1936
1937 if (nr_vals <= 1) {
1938 end = start;
1939 }
1940
1941 if (end.is_signed) {
1942 last->value.i = end.value.i + 1;
1943 } else {
1944 last->value.u = end.value.u + 1;
1945 }
1946
1947 ctf_field_class_enum_map_range(enum_decl, label, start.value.u, end.value.u);
1948 return 0;
e98a2d6e
PP
1949
1950error:
4164020e 1951 return ret;
e98a2d6e
PP
1952}
1953
4164020e
SM
1954static int visit_enum_decl(struct ctf_visitor_generate_ir *ctx, const char *name,
1955 struct ctf_node *container_cls, struct bt_list_head *enumerator_list,
1956 int has_body, struct ctf_field_class_enum **enum_decl)
e98a2d6e 1957{
4164020e
SM
1958 int ret = 0;
1959 GQuark qdummy_id;
1960 struct ctf_field_class_int *integer_decl = NULL;
1961
1962 BT_ASSERT(enum_decl);
1963 *enum_decl = NULL;
1964
1965 /* For named enum (without body), lookup in declaration scope */
1966 if (!has_body) {
1967 if (!name) {
1968 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1969 "Bodyless enumeration field class: missing name.");
1970 ret = -EPERM;
1971 goto error;
1972 }
1973
1974 *enum_decl = ctx_decl_scope_lookup_enum(ctx, ctx->current_scope, name, -1, true);
1975 if (!*enum_decl) {
1976 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: "
1977 "name=\"enum %s\"",
1978 name);
1979 ret = -EINVAL;
1980 goto error;
1981 }
1982 } else {
1983 struct ctf_node *iter;
1984 struct uori last_value = {
1985 .is_signed = false,
1986 .value =
1987 {
1988 .u = 0,
1989 },
1990 };
1991
1992 if (name) {
1993 if (ctx_decl_scope_lookup_enum(ctx, ctx->current_scope, name, 1, false)) {
1994 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
1995 "Enumeration field class already declared in local scope: "
1996 "name=\"enum %s\"",
1997 name);
1998 ret = -EINVAL;
1999 goto error;
2000 }
2001 }
2002
2003 if (!container_cls) {
2004 integer_decl = ctf_field_class_as_int(
2005 ctx_decl_scope_lookup_alias(ctx, ctx->current_scope, "int", -1, true));
2006 if (!integer_decl) {
2007 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2008 "Cannot find implicit `int` field class alias for enumeration field class.");
2009 ret = -EINVAL;
2010 goto error;
2011 }
2012 } else {
2013 ctf_field_class *decl;
2014
2015 ret = visit_field_class_declarator(ctx, container_cls, &qdummy_id, NULL, &decl, NULL);
2016 if (ret) {
2017 BT_ASSERT(!decl);
2018 ret = -EINVAL;
2019 goto error;
2020 }
2021
2022 integer_decl = ctf_field_class_as_int(decl);
2023 }
2024
2025 BT_ASSERT(integer_decl);
2026
2027 if (integer_decl->base.base.type != CTF_FIELD_CLASS_TYPE_INT) {
2028 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2029 "Container field class for enumeration field class is not an integer field class: "
2030 "fc-type=%d",
2031 integer_decl->base.base.type);
2032 ret = -EINVAL;
2033 goto error;
2034 }
2035
2036 *enum_decl = ctf_field_class_enum_create();
2037 BT_ASSERT(*enum_decl);
2038 (*enum_decl)->base.base.base.alignment = integer_decl->base.base.alignment;
2039 ctf_field_class_int_copy_content(&(*enum_decl)->base, integer_decl);
2040 last_value.is_signed = (*enum_decl)->base.is_signed;
2041
2042 bt_list_for_each_entry (iter, enumerator_list, siblings) {
2043 ret = visit_enum_decl_entry(ctx, iter, *enum_decl, &last_value);
2044 if (ret) {
2045 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
2046 "Cannot visit enumeration field class entry: "
2047 "ret=%d",
2048 ret);
2049 goto error;
2050 }
2051 }
2052
2053 if (name) {
2054 ret = ctx_decl_scope_register_enum(ctx, ctx->current_scope, name, *enum_decl);
2055 if (ret) {
2056 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2057 "Cannot register enumeration field class in declaration scope: "
2058 "ret=%d",
2059 ret);
2060 goto error;
2061 }
2062 }
2063 }
2064
2065 goto end;
e98a2d6e
PP
2066
2067error:
4164020e
SM
2068 ctf_field_class_destroy(&(*enum_decl)->base.base.base);
2069 *enum_decl = NULL;
e98a2d6e 2070
44c440bc 2071end:
4164020e
SM
2072 ctf_field_class_destroy(&integer_decl->base.base);
2073 integer_decl = NULL;
2074 return ret;
e98a2d6e
PP
2075}
2076
4164020e
SM
2077static int visit_field_class_specifier(struct ctf_visitor_generate_ir *ctx,
2078 struct ctf_node *cls_specifier_list,
2079 struct ctf_field_class **decl)
e98a2d6e 2080{
4164020e
SM
2081 int ret = 0;
2082 GString *str = NULL;
2083
2084 *decl = NULL;
2085 str = g_string_new("");
2086 ret = get_class_specifier_list_name(ctx, cls_specifier_list, str);
2087 if (ret) {
2088 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2089 cls_specifier_list, "Cannot get field class specifier list's name: ret=%d", ret);
2090 goto error;
2091 }
2092
2093 *decl = ctx_decl_scope_lookup_alias(ctx, ctx->current_scope, str->str, -1, true);
2094 if (!*decl) {
2095 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
2096 "Cannot find field class alias: name=\"%s\"", str->str);
2097 ret = -EINVAL;
2098 goto error;
2099 }
2100
2101 goto end;
e98a2d6e
PP
2102
2103error:
4164020e
SM
2104 ctf_field_class_destroy(*decl);
2105 *decl = NULL;
44c440bc
PP
2106
2107end:
4164020e
SM
2108 if (str) {
2109 g_string_free(str, TRUE);
2110 }
e98a2d6e 2111
4164020e 2112 return ret;
e98a2d6e
PP
2113}
2114
4164020e
SM
2115static int visit_integer_decl(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *expressions,
2116 struct ctf_field_class_int **integer_decl)
e98a2d6e 2117{
4164020e
SM
2118 int set = 0;
2119 int ret = 0;
2120 int signedness = 0;
2121 struct ctf_node *expression;
2122 uint64_t alignment = 0, size = 0;
2123 struct ctf_clock_class *mapped_clock_class = NULL;
2124 enum ctf_encoding encoding = CTF_ENCODING_NONE;
2125 bt_field_class_integer_preferred_display_base base =
2126 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
2127 enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
2128
2129 *integer_decl = NULL;
2130
2131 bt_list_for_each_entry (expression, expressions, siblings) {
2132 struct ctf_node *left, *right;
2133
2134 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left, struct ctf_node, siblings);
2135 right =
2136 _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.right, struct ctf_node, siblings);
2137
2138 if (left->u.unary_expression.type != UNARY_STRING) {
2139 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left, "Unexpected unary expression type: type=%d",
2140 left->u.unary_expression.type);
2141 ret = -EINVAL;
2142 goto error;
2143 }
2144
2145 if (strcmp(left->u.unary_expression.u.string, "signed") == 0) {
2146 if (_IS_SET(&set, _INTEGER_SIGNED_SET)) {
2147 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "signed", "integer field class");
2148 ret = -EPERM;
2149 goto error;
2150 }
2151
2152 signedness = get_boolean(ctx, right);
2153 if (signedness < 0) {
2154 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2155 right,
2156 "Invalid boolean value for integer field class's `signed` attribute: "
2157 "ret=%d",
2158 ret);
2159 ret = -EINVAL;
2160 goto error;
2161 }
2162
2163 _SET(&set, _INTEGER_SIGNED_SET);
2164 } else if (strcmp(left->u.unary_expression.u.string, "byte_order") == 0) {
2165 if (_IS_SET(&set, _INTEGER_BYTE_ORDER_SET)) {
2166 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "byte_order", "integer field class");
2167 ret = -EPERM;
2168 goto error;
2169 }
2170
2171 byte_order = get_real_byte_order(ctx, right);
2172 if (byte_order == CTF_BYTE_ORDER_UNKNOWN) {
2173 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2174 right,
2175 "Invalid `byte_order` attribute in integer field class: "
2176 "ret=%d",
2177 ret);
2178 ret = -EINVAL;
2179 goto error;
2180 }
2181
2182 _SET(&set, _INTEGER_BYTE_ORDER_SET);
2183 } else if (strcmp(left->u.unary_expression.u.string, "size") == 0) {
2184 if (_IS_SET(&set, _INTEGER_SIZE_SET)) {
2185 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "size", "integer field class");
2186 ret = -EPERM;
2187 goto error;
2188 }
2189
2190 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
2191 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2192 "Invalid `size` attribute in integer field class: "
2193 "expecting unsigned constant integer: "
2194 "node-type=%d",
2195 right->u.unary_expression.type);
2196 ret = -EINVAL;
2197 goto error;
2198 }
2199
2200 size = right->u.unary_expression.u.unsigned_constant;
2201 if (size == 0) {
2202 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2203 "Invalid `size` attribute in integer field class: "
2204 "expecting positive constant integer: "
2205 "size=%" PRIu64,
2206 size);
2207 ret = -EINVAL;
2208 goto error;
2209 } else if (size > 64) {
2210 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2211 right,
2212 "Invalid `size` attribute in integer field class: "
2213 "integer fields over 64 bits are not supported as of this version: "
2214 "size=%" PRIu64,
2215 size);
2216 ret = -EINVAL;
2217 goto error;
2218 }
2219
2220 _SET(&set, _INTEGER_SIZE_SET);
2221 } else if (strcmp(left->u.unary_expression.u.string, "align") == 0) {
2222 if (_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2223 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "align", "integer field class");
2224 ret = -EPERM;
2225 goto error;
2226 }
2227
2228 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
2229 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2230 "Invalid `align` attribute in integer field class: "
2231 "expecting unsigned constant integer: "
2232 "node-type=%d",
2233 right->u.unary_expression.type);
2234 ret = -EINVAL;
2235 goto error;
2236 }
2237
2238 alignment = right->u.unary_expression.u.unsigned_constant;
2239 if (!is_align_valid(alignment)) {
2240 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2241 "Invalid `align` attribute in integer field class: "
2242 "expecting power of two: "
2243 "align=%" PRIu64,
2244 alignment);
2245 ret = -EINVAL;
2246 goto error;
2247 }
2248
2249 _SET(&set, _INTEGER_ALIGN_SET);
2250 } else if (strcmp(left->u.unary_expression.u.string, "base") == 0) {
2251 if (_IS_SET(&set, _INTEGER_BASE_SET)) {
2252 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "base", "integer field class");
2253 ret = -EPERM;
2254 goto error;
2255 }
2256
2257 switch (right->u.unary_expression.type) {
2258 case UNARY_UNSIGNED_CONSTANT:
2259 {
2260 uint64_t constant = right->u.unary_expression.u.unsigned_constant;
2261
2262 switch (constant) {
2263 case 2:
2264 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY;
2265 break;
2266 case 8:
2267 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL;
2268 break;
2269 case 10:
2270 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
2271 break;
2272 case 16:
2273 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
2274 break;
2275 default:
2276 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2277 right,
2278 "Invalid `base` attribute in integer field class: "
2279 "base=%" PRIu64,
2280 right->u.unary_expression.u.unsigned_constant);
2281 ret = -EINVAL;
2282 goto error;
2283 }
2284 break;
2285 }
2286 case UNARY_STRING:
2287 {
2288 char *s_right =
2289 ctf_ast_concatenate_unary_strings(&expression->u.ctf_expression.right);
2290 if (!s_right) {
2291 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2292 right,
2293 "Unexpected unary expression for integer field class's `base` attribute.");
2294 ret = -EINVAL;
2295 goto error;
2296 }
2297
2298 if (strcmp(s_right, "decimal") == 0 || strcmp(s_right, "dec") == 0 ||
2299 strcmp(s_right, "d") == 0 || strcmp(s_right, "i") == 0 ||
2300 strcmp(s_right, "u") == 0) {
2301 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
2302 } else if (strcmp(s_right, "hexadecimal") == 0 || strcmp(s_right, "hex") == 0 ||
2303 strcmp(s_right, "x") == 0 || strcmp(s_right, "X") == 0 ||
2304 strcmp(s_right, "p") == 0) {
2305 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
2306 } else if (strcmp(s_right, "octal") == 0 || strcmp(s_right, "oct") == 0 ||
2307 strcmp(s_right, "o") == 0) {
2308 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL;
2309 } else if (strcmp(s_right, "binary") == 0 || strcmp(s_right, "b") == 0) {
2310 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY;
2311 } else {
2312 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2313 right,
2314 "Unexpected unary expression for integer field class's `base` attribute: "
2315 "base=\"%s\"",
2316 s_right);
2317 g_free(s_right);
2318 ret = -EINVAL;
2319 goto error;
2320 }
2321
2322 g_free(s_right);
2323 break;
2324 }
2325 default:
2326 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2327 right, "Invalid `base` attribute in integer field class: "
2328 "expecting unsigned constant integer or unary string.");
2329 ret = -EINVAL;
2330 goto error;
2331 }
2332
2333 _SET(&set, _INTEGER_BASE_SET);
2334 } else if (strcmp(left->u.unary_expression.u.string, "encoding") == 0) {
2335 char *s_right;
2336
2337 if (_IS_SET(&set, _INTEGER_ENCODING_SET)) {
2338 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "encoding", "integer field class");
2339 ret = -EPERM;
2340 goto error;
2341 }
2342
2343 if (right->u.unary_expression.type != UNARY_STRING) {
2344 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2345 right, "Invalid `encoding` attribute in integer field class: "
2346 "expecting unary string.");
2347 ret = -EINVAL;
2348 goto error;
2349 }
2350
2351 s_right = ctf_ast_concatenate_unary_strings(&expression->u.ctf_expression.right);
2352 if (!s_right) {
2353 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2354 right,
2355 "Unexpected unary expression for integer field class's `encoding` attribute.");
2356 ret = -EINVAL;
2357 goto error;
2358 }
2359
2360 if (strcmp(s_right, "UTF8") == 0 || strcmp(s_right, "utf8") == 0 ||
2361 strcmp(s_right, "utf-8") == 0 || strcmp(s_right, "UTF-8") == 0 ||
2362 strcmp(s_right, "ASCII") == 0 || strcmp(s_right, "ascii") == 0) {
2363 encoding = CTF_ENCODING_UTF8;
2364 } else if (strcmp(s_right, "none") == 0) {
2365 encoding = CTF_ENCODING_NONE;
2366 } else {
2367 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2368 right,
2369 "Invalid `encoding` attribute in integer field class: "
2370 "unknown encoding: encoding=\"%s\"",
2371 s_right);
2372 g_free(s_right);
2373 ret = -EINVAL;
2374 goto error;
2375 }
2376
2377 g_free(s_right);
2378 _SET(&set, _INTEGER_ENCODING_SET);
2379 } else if (strcmp(left->u.unary_expression.u.string, "map") == 0) {
2380 const char *clock_name;
2381
2382 if (_IS_SET(&set, _INTEGER_MAP_SET)) {
2383 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "map", "integer field class");
2384 ret = -EPERM;
2385 goto error;
2386 }
2387
2388 if (right->u.unary_expression.type != UNARY_STRING) {
2389 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2390 "Invalid `map` attribute in integer field class: "
2391 "expecting unary string.");
2392 ret = -EINVAL;
2393 goto error;
2394 }
2395
2396 clock_name = get_map_clock_name_value(&expression->u.ctf_expression.right);
2397 if (!clock_name) {
2398 char *s_right =
2399 ctf_ast_concatenate_unary_strings(&expression->u.ctf_expression.right);
2400
2401 if (!s_right) {
2402 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2403 right,
2404 "Unexpected unary expression for integer field class's `map` attribute.");
2405 ret = -EINVAL;
2406 goto error;
2407 }
2408
2409 _BT_COMP_LOGE_NODE(right,
2410 "Invalid `map` attribute in integer field class: "
2411 "cannot find clock class at this point: name=\"%s\"",
2412 s_right);
2413 _SET(&set, _INTEGER_MAP_SET);
2414 g_free(s_right);
2415 continue;
2416 }
2417
2418 mapped_clock_class =
2419 ctf_trace_class_borrow_clock_class_by_name(ctx->ctf_tc, clock_name);
2420 if (!mapped_clock_class) {
2421 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2422 right,
2423 "Invalid `map` attribute in integer field class: "
2424 "cannot find clock class at this point: name=\"%s\"",
2425 clock_name);
2426 ret = -EINVAL;
2427 goto error;
2428 }
2429
2430 _SET(&set, _INTEGER_MAP_SET);
2431 } else {
2432 _BT_COMP_LOGW_NODE(left,
2433 "Unknown attribute in integer field class: "
2434 "attr-name=\"%s\"",
2435 left->u.unary_expression.u.string);
2436 }
2437 }
2438
2439 if (!_IS_SET(&set, _INTEGER_SIZE_SET)) {
2440 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2441 "Missing `size` attribute in integer field class.");
2442 ret = -EPERM;
2443 goto error;
2444 }
2445
2446 if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2447 if (size % CHAR_BIT) {
2448 /* Bit-packed alignment */
2449 alignment = 1;
2450 } else {
2451 /* Byte-packed alignment */
2452 alignment = CHAR_BIT;
2453 }
2454 }
2455
2456 *integer_decl = ctf_field_class_int_create();
2457 BT_ASSERT(*integer_decl);
2458 (*integer_decl)->base.base.alignment = alignment;
2459 (*integer_decl)->base.byte_order = byte_order;
2460 (*integer_decl)->base.size = size;
2461 (*integer_decl)->is_signed = (signedness > 0);
2462 (*integer_decl)->disp_base = base;
2463 (*integer_decl)->encoding = encoding;
2464 (*integer_decl)->mapped_clock_class = mapped_clock_class;
2465 return 0;
e98a2d6e
PP
2466
2467error:
4164020e
SM
2468 ctf_field_class_destroy(&(*integer_decl)->base.base);
2469 *integer_decl = NULL;
2470 return ret;
e98a2d6e
PP
2471}
2472
4164020e
SM
2473static int visit_floating_point_number_decl(struct ctf_visitor_generate_ir *ctx,
2474 struct bt_list_head *expressions,
2475 struct ctf_field_class_float **float_decl)
e98a2d6e 2476{
4164020e
SM
2477 int set = 0;
2478 int ret = 0;
2479 struct ctf_node *expression;
2480 uint64_t alignment = 1, exp_dig = 0, mant_dig = 0;
2481 enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
2482
2483 *float_decl = NULL;
2484
2485 bt_list_for_each_entry (expression, expressions, siblings) {
2486 struct ctf_node *left, *right;
2487
2488 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left, struct ctf_node, siblings);
2489 right =
2490 _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.right, struct ctf_node, siblings);
2491
2492 if (left->u.unary_expression.type != UNARY_STRING) {
2493 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left, "Unexpected unary expression type: type=%d",
2494 left->u.unary_expression.type);
2495 ret = -EINVAL;
2496 goto error;
2497 }
2498
2499 if (strcmp(left->u.unary_expression.u.string, "byte_order") == 0) {
2500 if (_IS_SET(&set, _FLOAT_BYTE_ORDER_SET)) {
2501 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "byte_order",
2502 "floating point number field class");
2503 ret = -EPERM;
2504 goto error;
2505 }
2506
2507 byte_order = get_real_byte_order(ctx, right);
2508 if (byte_order == CTF_BYTE_ORDER_UNKNOWN) {
2509 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2510 right,
2511 "Invalid `byte_order` attribute in floating point number field class: "
2512 "ret=%d",
2513 ret);
2514 ret = -EINVAL;
2515 goto error;
2516 }
2517
2518 _SET(&set, _FLOAT_BYTE_ORDER_SET);
2519 } else if (strcmp(left->u.unary_expression.u.string, "exp_dig") == 0) {
2520 if (_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
2521 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "exp_dig",
2522 "floating point number field class");
2523 ret = -EPERM;
2524 goto error;
2525 }
2526
2527 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
2528 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2529 right,
2530 "Invalid `exp_dig` attribute in floating point number field class: "
2531 "expecting unsigned constant integer: "
2532 "node-type=%d",
2533 right->u.unary_expression.type);
2534 ret = -EINVAL;
2535 goto error;
2536 }
2537
2538 exp_dig = right->u.unary_expression.u.unsigned_constant;
2539 _SET(&set, _FLOAT_EXP_DIG_SET);
2540 } else if (strcmp(left->u.unary_expression.u.string, "mant_dig") == 0) {
2541 if (_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
2542 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "mant_dig",
2543 "floating point number field class");
2544 ret = -EPERM;
2545 goto error;
2546 }
2547
2548 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
2549 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2550 right,
2551 "Invalid `mant_dig` attribute in floating point number field class: "
2552 "expecting unsigned constant integer: "
2553 "node-type=%d",
2554 right->u.unary_expression.type);
2555 ret = -EINVAL;
2556 goto error;
2557 }
2558
2559 mant_dig = right->u.unary_expression.u.unsigned_constant;
2560 _SET(&set, _FLOAT_MANT_DIG_SET);
2561 } else if (strcmp(left->u.unary_expression.u.string, "align") == 0) {
2562 if (_IS_SET(&set, _FLOAT_ALIGN_SET)) {
2563 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "align",
2564 "floating point number field class");
2565 ret = -EPERM;
2566 goto error;
2567 }
2568
2569 if (right->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
2570 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2571 right,
2572 "Invalid `align` attribute in floating point number field class: "
2573 "expecting unsigned constant integer: "
2574 "node-type=%d",
2575 right->u.unary_expression.type);
2576 ret = -EINVAL;
2577 goto error;
2578 }
2579
2580 alignment = right->u.unary_expression.u.unsigned_constant;
2581
2582 if (!is_align_valid(alignment)) {
2583 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2584 right,
2585 "Invalid `align` attribute in floating point number field class: "
2586 "expecting power of two: "
2587 "align=%" PRIu64,
2588 alignment);
2589 ret = -EINVAL;
2590 goto error;
2591 }
2592
2593 _SET(&set, _FLOAT_ALIGN_SET);
2594 } else {
2595 _BT_COMP_LOGW_NODE(left,
2596 "Unknown attribute in floating point number field class: "
2597 "attr-name=\"%s\"",
2598 left->u.unary_expression.u.string);
2599 }
2600 }
2601
2602 if (!_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
2603 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2604 "Missing `mant_dig` attribute in floating point number field class.");
2605 ret = -EPERM;
2606 goto error;
2607 }
2608
2609 if (!_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
2610 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2611 "Missing `exp_dig` attribute in floating point number field class.");
2612 ret = -EPERM;
2613 goto error;
2614 }
2615
2616 if (mant_dig != 24 && mant_dig != 53) {
2617 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53.");
2618 ret = -EPERM;
2619 goto error;
2620 }
2621
2622 if (mant_dig == 24 && exp_dig != 8) {
2623 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2624 "`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2625 ret = -EPERM;
2626 goto error;
2627 }
2628
2629 if (mant_dig == 53 && exp_dig != 11) {
2630 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
2631 "`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2632 ret = -EPERM;
2633 goto error;
2634 }
2635
2636 if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2637 if ((mant_dig + exp_dig) % CHAR_BIT) {
2638 /* Bit-packed alignment */
2639 alignment = 1;
2640 } else {
2641 /* Byte-packed alignment */
2642 alignment = CHAR_BIT;
2643 }
2644 }
2645
2646 *float_decl = ctf_field_class_float_create();
2647 BT_ASSERT(*float_decl);
2648 (*float_decl)->base.base.alignment = alignment;
2649 (*float_decl)->base.byte_order = byte_order;
2650 (*float_decl)->base.size = mant_dig + exp_dig;
2651 return 0;
e98a2d6e
PP
2652
2653error:
4164020e
SM
2654 ctf_field_class_destroy(&(*float_decl)->base.base);
2655 *float_decl = NULL;
2656 return ret;
e98a2d6e
PP
2657}
2658
4164020e
SM
2659static int visit_string_decl(struct ctf_visitor_generate_ir *ctx, struct bt_list_head *expressions,
2660 struct ctf_field_class_string **string_decl)
e98a2d6e 2661{
4164020e
SM
2662 int set = 0;
2663 int ret = 0;
2664 struct ctf_node *expression;
2665 enum ctf_encoding encoding = CTF_ENCODING_UTF8;
2666
2667 *string_decl = NULL;
2668
2669 bt_list_for_each_entry (expression, expressions, siblings) {
2670 struct ctf_node *left, *right;
2671
2672 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left, struct ctf_node, siblings);
2673 right =
2674 _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.right, struct ctf_node, siblings);
2675
2676 if (left->u.unary_expression.type != UNARY_STRING) {
2677 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left, "Unexpected unary expression type: type=%d",
2678 left->u.unary_expression.type);
2679 ret = -EINVAL;
2680 goto error;
2681 }
2682
2683 if (strcmp(left->u.unary_expression.u.string, "encoding") == 0) {
2684 char *s_right;
2685
2686 if (_IS_SET(&set, _STRING_ENCODING_SET)) {
2687 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "encoding", "string field class");
2688 ret = -EPERM;
2689 goto error;
2690 }
2691
2692 if (right->u.unary_expression.type != UNARY_STRING) {
2693 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2694 right, "Invalid `encoding` attribute in string field class: "
2695 "expecting unary string.");
2696 ret = -EINVAL;
2697 goto error;
2698 }
2699
2700 s_right = ctf_ast_concatenate_unary_strings(&expression->u.ctf_expression.right);
2701 if (!s_right) {
2702 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2703 right,
2704 "Unexpected unary expression for string field class's `encoding` attribute.");
2705 ret = -EINVAL;
2706 goto error;
2707 }
2708
2709 if (strcmp(s_right, "UTF8") == 0 || strcmp(s_right, "utf8") == 0 ||
2710 strcmp(s_right, "utf-8") == 0 || strcmp(s_right, "UTF-8") == 0 ||
2711 strcmp(s_right, "ASCII") == 0 || strcmp(s_right, "ascii") == 0) {
2712 encoding = CTF_ENCODING_UTF8;
2713 } else if (strcmp(s_right, "none") == 0) {
2714 encoding = CTF_ENCODING_NONE;
2715 } else {
2716 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2717 right,
2718 "Invalid `encoding` attribute in string field class: "
2719 "unknown encoding: encoding=\"%s\"",
2720 s_right);
2721 g_free(s_right);
2722 ret = -EINVAL;
2723 goto error;
2724 }
2725
2726 g_free(s_right);
2727 _SET(&set, _STRING_ENCODING_SET);
2728 } else {
2729 _BT_COMP_LOGW_NODE(left,
2730 "Unknown attribute in string field class: "
2731 "attr-name=\"%s\"",
2732 left->u.unary_expression.u.string);
2733 }
2734 }
2735
2736 *string_decl = ctf_field_class_string_create();
2737 BT_ASSERT(*string_decl);
2738 (*string_decl)->encoding = encoding;
2739 return 0;
e98a2d6e
PP
2740
2741error:
4164020e
SM
2742 ctf_field_class_destroy(&(*string_decl)->base);
2743 *string_decl = NULL;
2744 return ret;
e98a2d6e
PP
2745}
2746
4164020e
SM
2747static int visit_field_class_specifier_list(struct ctf_visitor_generate_ir *ctx,
2748 struct ctf_node *ts_list, struct ctf_field_class **decl)
e98a2d6e 2749{
4164020e
SM
2750 int ret = 0;
2751 struct ctf_node *first, *node;
2752
2753 *decl = NULL;
2754
2755 if (ts_list->type != NODE_TYPE_SPECIFIER_LIST) {
2756 _BT_COMP_LOGE_APPEND_CAUSE_NODE(ts_list, "Unexpected node type: node-type=%d",
2757 ts_list->type);
2758 ret = -EINVAL;
2759 goto error;
2760 }
2761
2762 first = _BT_LIST_FIRST_ENTRY(&ts_list->u.field_class_specifier_list.head, struct ctf_node,
2763 siblings);
2764 if (first->type != NODE_TYPE_SPECIFIER) {
2765 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first, "Unexpected node type: node-type=%d", first->type);
2766 ret = -EINVAL;
2767 goto error;
2768 }
2769
2770 node = first->u.field_class_specifier.node;
2771
2772 switch (first->u.field_class_specifier.type) {
2773 case TYPESPEC_INTEGER:
2774 {
2775 ctf_field_class_int *int_decl;
2776
2777 ret = visit_integer_decl(ctx, &node->u.integer.expressions, &int_decl);
2778 if (ret) {
2779 BT_ASSERT(!int_decl);
2780 goto error;
2781 }
2782
2783 *decl = &int_decl->base.base;
2784 break;
2785 }
2786 case TYPESPEC_FLOATING_POINT:
2787 {
2788 ctf_field_class_float *float_decl;
2789
2790 ret =
2791 visit_floating_point_number_decl(ctx, &node->u.floating_point.expressions, &float_decl);
2792 if (ret) {
2793 BT_ASSERT(!float_decl);
2794 goto error;
2795 }
2796
2797 *decl = &float_decl->base.base;
2798 break;
2799 }
2800 case TYPESPEC_STRING:
2801 {
2802 ctf_field_class_string *string_decl;
2803
2804 ret = visit_string_decl(ctx, &node->u.string.expressions, &string_decl);
2805 if (ret) {
2806 BT_ASSERT(!string_decl);
2807 goto error;
2808 }
2809
2810 *decl = &string_decl->base;
2811 break;
2812 }
2813 case TYPESPEC_STRUCT:
2814 {
2815 ctf_field_class_struct *struct_decl;
2816
2817 ret = visit_struct_decl(ctx, node->u._struct.name, &node->u._struct.declaration_list,
2818 node->u._struct.has_body, &node->u._struct.min_align, &struct_decl);
2819 if (ret) {
2820 BT_ASSERT(!struct_decl);
2821 goto error;
2822 }
2823
2824 *decl = &struct_decl->base;
2825 break;
2826 }
2827 case TYPESPEC_VARIANT:
2828 {
2829 ctf_field_class_variant *variant_decl;
2830
2831 ret = visit_variant_decl(ctx, node->u.variant.name, node->u.variant.choice,
2832 &node->u.variant.declaration_list, node->u.variant.has_body,
2833 &variant_decl);
2834 if (ret) {
2835 BT_ASSERT(!variant_decl);
2836 goto error;
2837 }
2838
2839 *decl = &variant_decl->base;
2840 break;
2841 }
2842 case TYPESPEC_ENUM:
2843 {
2844 ctf_field_class_enum *enum_decl;
2845
2846 ret = visit_enum_decl(ctx, node->u._enum.enum_id, node->u._enum.container_field_class,
2847 &node->u._enum.enumerator_list, node->u._enum.has_body, &enum_decl);
2848 if (ret) {
2849 BT_ASSERT(!enum_decl);
2850 goto error;
2851 }
2852
2853 *decl = &enum_decl->base.base.base;
2854 break;
2855 }
2856 case TYPESPEC_VOID:
2857 case TYPESPEC_CHAR:
2858 case TYPESPEC_SHORT:
2859 case TYPESPEC_INT:
2860 case TYPESPEC_LONG:
2861 case TYPESPEC_FLOAT:
2862 case TYPESPEC_DOUBLE:
2863 case TYPESPEC_SIGNED:
2864 case TYPESPEC_UNSIGNED:
2865 case TYPESPEC_BOOL:
2866 case TYPESPEC_COMPLEX:
2867 case TYPESPEC_IMAGINARY:
2868 case TYPESPEC_CONST:
2869 case TYPESPEC_ID_TYPE:
2870 ret = visit_field_class_specifier(ctx, ts_list, decl);
2871 if (ret) {
2872 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first, "Cannot visit field class specifier: ret=%d",
2873 ret);
2874 BT_ASSERT(!*decl);
2875 goto error;
2876 }
2877 break;
2878 default:
2879 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first,
2880 "Unexpected field class specifier type: node-type=%d",
2881 first->u.field_class_specifier.type);
2882 ret = -EINVAL;
2883 goto error;
2884 }
2885
2886 BT_ASSERT(*decl);
2887 return 0;
e98a2d6e
PP
2888
2889error:
4164020e
SM
2890 ctf_field_class_destroy(*decl);
2891 *decl = NULL;
2892 return ret;
e98a2d6e
PP
2893}
2894
4164020e
SM
2895static int visit_event_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node,
2896 struct ctf_event_class *event_class, uint64_t *stream_id,
2897 int *set)
e98a2d6e 2898{
4164020e
SM
2899 int ret = 0;
2900 char *left = NULL;
2901
2902 switch (node->type) {
2903 case NODE_TYPEDEF:
2904 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
2905 &node->u.field_class_def.field_class_declarators);
2906 if (ret) {
2907 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot add field class found in event class.");
2908 goto error;
2909 }
2910 break;
2911 case NODE_TYPEALIAS:
2912 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
2913 node->u.field_class_alias.alias);
2914 if (ret) {
2915 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
2916 "Cannot add field class alias found in event class.");
2917 goto error;
2918 }
2919 break;
2920 case NODE_CTF_EXPRESSION:
2921 {
2922 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
2923 if (!left) {
2924 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
2925 ret = -EINVAL;
2926 goto error;
2927 }
2928
2929 if (strcmp(left, "name") == 0) {
2930 /* This is already known at this stage */
2931 if (_IS_SET(set, _EVENT_NAME_SET)) {
2932 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "name", "event class");
2933 ret = -EPERM;
2934 goto error;
2935 }
2936
2937 _SET(set, _EVENT_NAME_SET);
2938 } else if (strcmp(left, "id") == 0) {
2939 int64_t id = -1;
2940
2941 if (_IS_SET(set, _EVENT_ID_SET)) {
2942 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "id", "event class");
2943 ret = -EPERM;
2944 goto error;
2945 }
2946
2947 ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, (uint64_t *) &id);
2948 /* Only read "id" if get_unary_unsigned() succeeded. */
2949 if (ret || (!ret && id < 0)) {
2950 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2951 node, "Unexpected unary expression for event class's `id` attribute.");
2952 ret = -EINVAL;
2953 goto error;
2954 }
2955
2956 event_class->id = id;
2957 _SET(set, _EVENT_ID_SET);
2958 } else if (strcmp(left, "stream_id") == 0) {
2959 if (_IS_SET(set, _EVENT_STREAM_ID_SET)) {
2960 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "stream_id", "event class");
2961 ret = -EPERM;
2962 goto error;
2963 }
2964
2965 ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, stream_id);
2966
2967 /*
2968 * Only read "stream_id" if get_unary_unsigned()
2969 * succeeded.
2970 */
2971 if (ret) {
2972 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
2973 node, "Unexpected unary expression for event class's `stream_id` attribute.");
2974 ret = -EINVAL;
2975 goto error;
2976 }
2977
2978 _SET(set, _EVENT_STREAM_ID_SET);
2979 } else if (strcmp(left, "context") == 0) {
2980 if (_IS_SET(set, _EVENT_CONTEXT_SET)) {
2981 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate `context` entry in event class.");
2982 ret = -EPERM;
2983 goto error;
2984 }
2985
2986 ret = visit_field_class_specifier_list(
2987 ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings),
2988 &event_class->spec_context_fc);
2989 if (ret) {
2990 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
2991 "Cannot create event class's context field class.");
2992 goto error;
2993 }
2994
2995 BT_ASSERT(event_class->spec_context_fc);
2996 _SET(set, _EVENT_CONTEXT_SET);
2997 } else if (strcmp(left, "fields") == 0) {
2998 if (_IS_SET(set, _EVENT_FIELDS_SET)) {
2999 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate `fields` entry in event class.");
3000 ret = -EPERM;
3001 goto error;
3002 }
3003
3004 ret = visit_field_class_specifier_list(
3005 ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings),
3006 &event_class->payload_fc);
3007 if (ret) {
3008 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3009 "Cannot create event class's payload field class.");
3010 goto error;
3011 }
3012
3013 BT_ASSERT(event_class->payload_fc);
3014 _SET(set, _EVENT_FIELDS_SET);
3015 } else if (strcmp(left, "loglevel") == 0) {
3016 uint64_t loglevel_value;
3017 bool is_log_level_known = true;
3018 bt_event_class_log_level log_level;
3019
3020 if (_IS_SET(set, _EVENT_LOG_LEVEL_SET)) {
3021 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "loglevel", "event class");
3022 ret = -EPERM;
3023 goto error;
3024 }
3025
3026 ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, &loglevel_value);
3027 if (ret) {
3028 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3029 node, "Unexpected unary expression for event class's `loglevel` attribute.");
3030 ret = -EINVAL;
3031 goto error;
3032 }
3033
3034 switch (loglevel_value) {
3035 case 0:
3036 log_level = BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY;
3037 break;
3038 case 1:
3039 log_level = BT_EVENT_CLASS_LOG_LEVEL_ALERT;
3040 break;
3041 case 2:
3042 log_level = BT_EVENT_CLASS_LOG_LEVEL_CRITICAL;
3043 break;
3044 case 3:
3045 log_level = BT_EVENT_CLASS_LOG_LEVEL_ERROR;
3046 break;
3047 case 4:
3048 log_level = BT_EVENT_CLASS_LOG_LEVEL_WARNING;
3049 break;
3050 case 5:
3051 log_level = BT_EVENT_CLASS_LOG_LEVEL_NOTICE;
3052 break;
3053 case 6:
3054 log_level = BT_EVENT_CLASS_LOG_LEVEL_INFO;
3055 break;
3056 case 7:
3057 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM;
3058 break;
3059 case 8:
3060 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM;
3061 break;
3062 case 9:
3063 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS;
3064 break;
3065 case 10:
3066 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE;
3067 break;
3068 case 11:
3069 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT;
3070 break;
3071 case 12:
3072 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION;
3073 break;
3074 case 13:
3075 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE;
3076 break;
3077 case 14:
3078 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG;
3079 break;
3080 default:
3081 is_log_level_known = false;
3082 _BT_COMP_LOGW_NODE(
3083 node,
3084 "Not setting event class's log level because its value is unknown: "
3085 "log-level=%" PRIu64,
3086 loglevel_value);
3087 }
3088
3089 if (is_log_level_known) {
3090 ctf_event_class_set_log_level(event_class, log_level);
3091 }
3092
3093 _SET(set, _EVENT_LOG_LEVEL_SET);
3094 } else if (strcmp(left, "model.emf.uri") == 0) {
3095 char *right;
3096
3097 if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) {
3098 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "model.emf.uri", "event class");
3099 ret = -EPERM;
3100 goto error;
3101 }
3102
3103 right = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.right);
3104 if (!right) {
3105 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3106 node,
3107 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3108 ret = -EINVAL;
3109 goto error;
3110 }
3111
3112 if (strlen(right) == 0) {
3113 _BT_COMP_LOGW_NODE(node, "Not setting event class's EMF URI because it's empty.");
3114 } else {
3115 g_string_assign(event_class->emf_uri, right);
3116 }
3117
3118 g_free(right);
3119 _SET(set, _EVENT_MODEL_EMF_URI_SET);
3120 } else {
3121 _BT_COMP_LOGW_NODE(node,
3122 "Unknown attribute in event class: "
3123 "attr-name=\"%s\"",
3124 left);
3125 }
3126
3127 g_free(left);
3128 left = NULL;
3129 break;
3130 }
3131 default:
3132 ret = -EPERM;
3133 goto error;
3134 }
3135
3136 goto end;
e98a2d6e
PP
3137
3138error:
4164020e 3139 g_free(left);
e98a2d6e 3140
44c440bc 3141end:
4164020e 3142 return ret;
e98a2d6e
PP
3143}
3144
4164020e 3145static char *get_event_decl_name(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
e98a2d6e 3146{
4164020e
SM
3147 char *left = NULL;
3148 char *name = NULL;
3149 struct ctf_node *iter;
3150 struct bt_list_head *decl_list = &node->u.event.declaration_list;
3151
3152 bt_list_for_each_entry (iter, decl_list, siblings) {
3153 if (iter->type != NODE_CTF_EXPRESSION) {
3154 continue;
3155 }
3156
3157 left = ctf_ast_concatenate_unary_strings(&iter->u.ctf_expression.left);
3158 if (!left) {
3159 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot concatenate unary strings.");
3160 goto error;
3161 }
3162
3163 if (strcmp(left, "name") == 0) {
3164 name = ctf_ast_concatenate_unary_strings(&iter->u.ctf_expression.right);
3165 if (!name) {
3166 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3167 iter, "Unexpected unary expression for event class's `name` attribute.");
3168 goto error;
3169 }
3170 }
3171
3172 g_free(left);
3173 left = NULL;
3174
3175 if (name) {
3176 break;
3177 }
3178 }
3179
3180 return name;
e98a2d6e
PP
3181
3182error:
4164020e
SM
3183 g_free(left);
3184 return NULL;
e98a2d6e
PP
3185}
3186
4164020e 3187static int visit_event_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
e98a2d6e 3188{
4164020e
SM
3189 int ret = 0;
3190 int set = 0;
3191 struct ctf_node *iter;
3192 uint64_t stream_id = 0;
3193 char *event_name = NULL;
3194 struct ctf_event_class *event_class = NULL;
3195 struct ctf_stream_class *stream_class = NULL;
3196 struct bt_list_head *decl_list = &node->u.event.declaration_list;
3197 bool pop_scope = false;
3198
3199 if (node->visited) {
3200 goto end;
3201 }
3202
3203 node->visited = TRUE;
3204 event_name = get_event_decl_name(ctx, node);
3205 if (!event_name) {
3206 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Missing `name` attribute in event class.");
3207 ret = -EPERM;
3208 goto error;
3209 }
3210
3211 event_class = ctf_event_class_create();
3212 BT_ASSERT(event_class);
3213 g_string_assign(event_class->name, event_name);
3214 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3215 pop_scope = true;
3216
3217 bt_list_for_each_entry (iter, decl_list, siblings) {
3218 ret = visit_event_decl_entry(ctx, iter, event_class, &stream_id, &set);
3219 if (ret) {
3220 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
3221 "Cannot visit event class's entry: "
3222 "ret=%d",
3223 ret);
3224 goto error;
3225 }
3226 }
3227
3228 if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) {
3229 /*
3230 * Allow missing stream_id if there is only a single
3231 * stream class.
3232 */
3233 switch (ctx->ctf_tc->stream_classes->len) {
3234 case 0:
3235 /* Create implicit stream class if there's none */
3236 stream_id = 0;
3237 stream_class = ctf_stream_class_create();
3238 BT_ASSERT(stream_class);
3239 stream_class->id = stream_id;
3240 g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class);
3241 break;
3242 case 1:
3243 /* Single stream class: get its ID */
3244 stream_class = (ctf_stream_class *) ctx->ctf_tc->stream_classes->pdata[0];
3245 stream_id = stream_class->id;
3246 break;
3247 default:
3248 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Missing `stream_id` attribute in event class.");
3249 ret = -EPERM;
3250 goto error;
3251 }
3252 }
3253
3254 /* We have the stream ID now; get the stream class if found */
3255 if (!stream_class) {
3256 stream_class = ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc, stream_id);
3257 if (!stream_class) {
3258 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3259 "Cannot find stream class at this point: "
3260 "id=%" PRId64,
3261 stream_id);
3262 ret = -EINVAL;
3263 goto error;
3264 }
3265 }
3266
3267 BT_ASSERT(stream_class);
3268
3269 if (!_IS_SET(&set, _EVENT_ID_SET)) {
3270 /* Allow only one event without ID per stream */
3271 if (stream_class->event_classes->len != 0) {
3272 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Missing `id` attribute in event class.");
3273 ret = -EPERM;
3274 goto error;
3275 }
3276
3277 /* Automatic ID */
3278 event_class->id = 0;
3279 }
3280
3281 if (ctf_stream_class_borrow_event_class_by_id(stream_class, event_class->id)) {
3282 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3283 "Duplicate event class (same ID) in the same stream class: "
3284 "id=%" PRId64,
3285 event_class->id);
3286 ret = -EEXIST;
3287 goto error;
3288 }
3289
3290 ctf_stream_class_append_event_class(stream_class, event_class);
3291 event_class = NULL;
3292 goto end;
e98a2d6e
PP
3293
3294error:
4164020e
SM
3295 ctf_event_class_destroy(event_class);
3296 event_class = NULL;
44c440bc 3297
4164020e
SM
3298 if (ret >= 0) {
3299 ret = -1;
3300 }
e98a2d6e 3301
1e649dff 3302end:
4164020e
SM
3303 if (pop_scope) {
3304 ctx_pop_scope(ctx);
3305 }
e98a2d6e 3306
4164020e 3307 g_free(event_name);
44c440bc 3308
4164020e 3309 return ret;
e98a2d6e
PP
3310}
3311
4164020e
SM
3312static int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir *ctx,
3313 struct ctf_field_class *fc)
56b43721 3314{
4164020e
SM
3315 struct ctf_clock_class *clock_class_to_map_to = NULL;
3316 struct ctf_field_class_int *int_fc = ctf_field_class_as_int(fc);
3317 int ret = 0;
3318 uint64_t clock_class_count;
3319
3320 if (!fc) {
3321 goto end;
3322 }
3323
3324 if (fc->type != CTF_FIELD_CLASS_TYPE_INT && fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
3325 goto end;
3326 }
3327
3328 if (int_fc->mapped_clock_class) {
3329 /* Already mapped */
3330 goto end;
3331 }
3332
3333 clock_class_count = ctx->ctf_tc->clock_classes->len;
3334
3335 switch (clock_class_count) {
3336 case 0:
3337 /*
3338 * No clock class exists in the trace at this point. Create an
3339 * implicit one at 1 GHz, named `default`, and use this clock
3340 * class.
3341 */
3342 clock_class_to_map_to = ctf_clock_class_create();
3343 BT_ASSERT(clock_class_to_map_to);
3344 clock_class_to_map_to->frequency = UINT64_C(1000000000);
3345 g_string_assign(clock_class_to_map_to->name, "default");
3346 BT_ASSERT(ret == 0);
3347 g_ptr_array_add(ctx->ctf_tc->clock_classes, clock_class_to_map_to);
3348 break;
3349 case 1:
3350 /*
3351 * Only one clock class exists in the trace at this point: use
3352 * this one.
3353 */
3354 clock_class_to_map_to = (ctf_clock_class *) ctx->ctf_tc->clock_classes->pdata[0];
3355 break;
3356 default:
3357 /*
3358 * Timestamp field not mapped to a clock class and there's more
3359 * than one clock class in the trace: this is an error.
3360 */
3361 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3362 "Timestamp field found with no mapped clock class, "
3363 "but there's more than one clock class in the trace at this point.");
3364 ret = -1;
3365 goto end;
3366 }
3367
3368 BT_ASSERT(clock_class_to_map_to);
3369 int_fc->mapped_clock_class = clock_class_to_map_to;
56b43721 3370
7bf5af54 3371end:
4164020e 3372 return ret;
7bf5af54 3373}
56b43721 3374
4164020e
SM
3375static int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir *ctx,
3376 struct ctf_field_class *root_fc,
3377 const char *field_name)
7bf5af54 3378{
4164020e
SM
3379 int ret = 0;
3380 uint64_t i, count;
3381 struct ctf_field_class_struct *struct_fc = (ctf_field_class_struct *) root_fc;
3382 struct ctf_field_class_variant *var_fc = (ctf_field_class_variant *) root_fc;
3383
3384 if (!root_fc) {
3385 goto end;
3386 }
3387
3388 if (root_fc->type != CTF_FIELD_CLASS_TYPE_STRUCT &&
3389 root_fc->type != CTF_FIELD_CLASS_TYPE_VARIANT) {
3390 goto end;
3391 }
3392
3393 if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
3394 count = struct_fc->members->len;
3395 } else {
3396 count = var_fc->options->len;
3397 }
3398
3399 for (i = 0; i < count; i++) {
3400 struct ctf_named_field_class *named_fc = NULL;
3401
3402 if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
3403 named_fc = ctf_field_class_struct_borrow_member_by_index(struct_fc, i);
3404 } else if (root_fc->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
3405 named_fc = ctf_field_class_variant_borrow_option_by_index(var_fc, i);
3406 } else {
3407 bt_common_abort();
3408 }
3409
3410 if (strcmp(named_fc->name->str, field_name) == 0) {
3411 ret = auto_map_field_to_trace_clock_class(ctx, named_fc->fc);
3412 if (ret) {
3413 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3414 "Cannot automatically map field to trace's clock class: "
3415 "field-name=\"%s\"",
3416 field_name);
3417 goto end;
3418 }
3419 }
3420
3421 ret = auto_map_fields_to_trace_clock_class(ctx, named_fc->fc, field_name);
3422 if (ret) {
3423 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
3424 "Cannot automatically map structure or variant field class's fields to trace's clock class: "
3425 "field-name=\"%s\", root-field-name=\"%s\"",
3426 field_name, named_fc->name->str);
3427 goto end;
3428 }
3429 }
56b43721
PP
3430
3431end:
4164020e 3432 return ret;
56b43721
PP
3433}
3434
4164020e
SM
3435static int visit_stream_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node,
3436 struct ctf_stream_class *stream_class, int *set)
e98a2d6e 3437{
4164020e
SM
3438 int ret = 0;
3439 char *left = NULL;
3440
3441 switch (node->type) {
3442 case NODE_TYPEDEF:
3443 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3444 &node->u.field_class_def.field_class_declarators);
3445 if (ret) {
3446 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot add field class found in stream class.");
3447 goto error;
3448 }
3449 break;
3450 case NODE_TYPEALIAS:
3451 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3452 node->u.field_class_alias.alias);
3453 if (ret) {
3454 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3455 "Cannot add field class alias found in stream class.");
3456 goto error;
3457 }
3458 break;
3459 case NODE_CTF_EXPRESSION:
3460 {
3461 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
3462 if (!left) {
3463 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
3464 ret = -EINVAL;
3465 goto error;
3466 }
3467
3468 if (strcmp(left, "id") == 0) {
3469 int64_t id;
3470
3471 if (_IS_SET(set, _STREAM_ID_SET)) {
3472 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "id", "stream declaration");
3473 ret = -EPERM;
3474 goto error;
3475 }
3476
3477 ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, (uint64_t *) &id);
3478
3479 /* Only read "id" if get_unary_unsigned() succeeded. */
3480 if (ret || (!ret && id < 0)) {
3481 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3482 node, "Unexpected unary expression for stream class's `id` attribute.");
3483 ret = -EINVAL;
3484 goto error;
3485 }
3486
3487 if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc, id)) {
3488 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3489 node, "Duplicate stream class (same ID): id=%" PRId64, id);
3490 ret = -EEXIST;
3491 goto error;
3492 }
3493
3494 stream_class->id = id;
3495 _SET(set, _STREAM_ID_SET);
3496 } else if (strcmp(left, "event.header") == 0) {
3497 if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) {
3498 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3499 "Duplicate `event.header` entry in stream class.");
3500 ret = -EPERM;
3501 goto error;
3502 }
3503
3504 ret = visit_field_class_specifier_list(
3505 ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings),
3506 &stream_class->event_header_fc);
3507 if (ret) {
3508 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3509 node, "Cannot create stream class's event header field class.");
3510 goto error;
3511 }
3512
3513 BT_ASSERT(stream_class->event_header_fc);
3514 ret = auto_map_fields_to_trace_clock_class(ctx, stream_class->event_header_fc,
3515 "timestamp");
3516 if (ret) {
3517 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3518 node,
3519 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3520 goto error;
3521 }
3522
3523 _SET(set, _STREAM_EVENT_HEADER_SET);
3524 } else if (strcmp(left, "event.context") == 0) {
3525 if (_IS_SET(set, _STREAM_EVENT_CONTEXT_SET)) {
3526 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3527 "Duplicate `event.context` entry in stream class.");
3528 ret = -EPERM;
3529 goto error;
3530 }
3531
3532 ret = visit_field_class_specifier_list(
3533 ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings),
3534 &stream_class->event_common_context_fc);
3535 if (ret) {
3536 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3537 node, "Cannot create stream class's event context field class.");
3538 goto error;
3539 }
3540
3541 BT_ASSERT(stream_class->event_common_context_fc);
3542 _SET(set, _STREAM_EVENT_CONTEXT_SET);
3543 } else if (strcmp(left, "packet.context") == 0) {
3544 if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) {
3545 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3546 node, "Duplicate `packet.context` entry in stream class.");
3547 ret = -EPERM;
3548 goto error;
3549 }
3550
3551 ret = visit_field_class_specifier_list(
3552 ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings),
3553 &stream_class->packet_context_fc);
3554 if (ret) {
3555 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3556 node, "Cannot create stream class's packet context field class.");
3557 goto error;
3558 }
3559
3560 BT_ASSERT(stream_class->packet_context_fc);
3561 ret = auto_map_fields_to_trace_clock_class(ctx, stream_class->packet_context_fc,
3562 "timestamp_begin");
3563 if (ret) {
3564 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3565 node,
3566 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3567 goto error;
3568 }
3569
3570 ret = auto_map_fields_to_trace_clock_class(ctx, stream_class->packet_context_fc,
3571 "timestamp_end");
3572 if (ret) {
3573 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3574 node,
3575 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3576 goto error;
3577 }
3578
3579 _SET(set, _STREAM_PACKET_CONTEXT_SET);
3580 } else {
3581 _BT_COMP_LOGW_NODE(node,
3582 "Unknown attribute in stream class: "
3583 "attr-name=\"%s\"",
3584 left);
3585 }
3586
3587 g_free(left);
3588 left = NULL;
3589 break;
3590 }
3591
3592 default:
3593 ret = -EPERM;
3594 goto error;
3595 }
3596
3597 return 0;
e98a2d6e
PP
3598
3599error:
4164020e
SM
3600 g_free(left);
3601 return ret;
e98a2d6e
PP
3602}
3603
4164020e 3604static int visit_stream_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
e98a2d6e 3605{
4164020e
SM
3606 int set = 0;
3607 int ret = 0;
3608 struct ctf_node *iter;
3609 struct ctf_stream_class *stream_class = NULL;
3610 struct bt_list_head *decl_list = &node->u.stream.declaration_list;
3611
3612 if (node->visited) {
3613 goto end;
3614 }
3615
3616 node->visited = TRUE;
3617 stream_class = ctf_stream_class_create();
3618 BT_ASSERT(stream_class);
3619 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3620
3621 bt_list_for_each_entry (iter, decl_list, siblings) {
3622 ret = visit_stream_decl_entry(ctx, iter, stream_class, &set);
3623 if (ret) {
3624 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
3625 "Cannot visit stream class's entry: "
3626 "ret=%d",
3627 ret);
3628 ctx_pop_scope(ctx);
3629 goto error;
3630 }
3631 }
3632
3633 ctx_pop_scope(ctx);
3634
3635 if (_IS_SET(&set, _STREAM_ID_SET)) {
3636 /* Check that packet header has `stream_id` field */
3637 struct ctf_named_field_class *named_fc = NULL;
3638
3639 if (!ctx->ctf_tc->packet_header_fc) {
3640 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Stream class has a `id` attribute, "
3641 "but trace has no packet header field class.");
3642 ret = -EINVAL;
3643 goto error;
3644 }
3645
3646 named_fc = ctf_field_class_struct_borrow_member_by_name(
3647 ctf_field_class_as_struct(ctx->ctf_tc->packet_header_fc), "stream_id");
3648 if (!named_fc) {
3649 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3650 node, "Stream class has a `id` attribute, "
3651 "but trace's packet header field class has no `stream_id` field.");
3652 ret = -EINVAL;
3653 goto error;
3654 }
3655
3656 if (named_fc->fc->type != CTF_FIELD_CLASS_TYPE_INT &&
3657 named_fc->fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
3658 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3659 node,
3660 "Stream class has a `id` attribute, "
3661 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3662 ret = -EINVAL;
3663 goto error;
3664 }
3665 } else {
3666 /* Allow only _one_ ID-less stream */
3667 if (ctx->ctf_tc->stream_classes->len != 0) {
3668 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3669 node,
3670 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3671 ret = -EPERM;
3672 goto error;
3673 }
3674
3675 /* Automatic ID: 0 */
3676 stream_class->id = 0;
3677 }
3678
3679 /*
3680 * Make sure that this stream class's ID is currently unique in
3681 * the trace.
3682 */
3683 if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc, stream_class->id)) {
3684 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate stream class (same ID): id=%" PRId64,
3685 stream_class->id);
3686 ret = -EINVAL;
3687 goto error;
3688 }
3689
3690 g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class);
3691 stream_class = NULL;
3692 goto end;
e98a2d6e
PP
3693
3694error:
4164020e
SM
3695 ctf_stream_class_destroy(stream_class);
3696 stream_class = NULL;
e98a2d6e 3697
1e649dff 3698end:
4164020e 3699 return ret;
e98a2d6e
PP
3700}
3701
4164020e
SM
3702static int visit_trace_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node,
3703 int *set)
e98a2d6e 3704{
4164020e
SM
3705 int ret = 0;
3706 char *left = NULL;
3707 uint64_t val;
3708
3709 switch (node->type) {
3710 case NODE_TYPEDEF:
3711 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3712 &node->u.field_class_def.field_class_declarators);
3713 if (ret) {
3714 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3715 node, "Cannot add field class found in trace (`trace` block).");
3716 goto error;
3717 }
3718 break;
3719 case NODE_TYPEALIAS:
3720 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3721 node->u.field_class_alias.alias);
3722 if (ret) {
3723 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3724 node, "Cannot add field class alias found in trace (`trace` block).");
3725 goto error;
3726 }
3727 break;
3728 case NODE_CTF_EXPRESSION:
3729 {
3730 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
3731 if (!left) {
3732 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
3733 ret = -EINVAL;
3734 goto error;
3735 }
3736
3737 if (strcmp(left, "major") == 0) {
3738 if (_IS_SET(set, _TRACE_MAJOR_SET)) {
3739 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "major", "trace");
3740 ret = -EPERM;
3741 goto error;
3742 }
3743
3744 ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, &val);
3745 if (ret) {
3746 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3747 node, "Unexpected unary expression for trace's `major` attribute.");
3748 ret = -EINVAL;
3749 goto error;
3750 }
3751
3752 if (val != 1) {
3753 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3754 "Invalid trace's `minor` attribute: expecting 1.");
3755 ret = -EINVAL;
3756 goto error;
3757 }
3758
3759 ctx->ctf_tc->major = val;
3760 _SET(set, _TRACE_MAJOR_SET);
3761 } else if (strcmp(left, "minor") == 0) {
3762 if (_IS_SET(set, _TRACE_MINOR_SET)) {
3763 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "minor", "trace");
3764 ret = -EPERM;
3765 goto error;
3766 }
3767
3768 ret = get_unary_unsigned(ctx, &node->u.ctf_expression.right, &val);
3769 if (ret) {
3770 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3771 node, "Unexpected unary expression for trace's `minor` attribute.");
3772 ret = -EINVAL;
3773 goto error;
3774 }
3775
3776 if (val != 8) {
3777 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3778 "Invalid trace's `minor` attribute: expecting 8.");
3779 ret = -EINVAL;
3780 goto error;
3781 }
3782
3783 ctx->ctf_tc->minor = val;
3784 _SET(set, _TRACE_MINOR_SET);
3785 } else if (strcmp(left, "uuid") == 0) {
3786 if (_IS_SET(set, _TRACE_UUID_SET)) {
3787 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "uuid", "trace");
3788 ret = -EPERM;
3789 goto error;
3790 }
3791
3792 ret = get_unary_uuid(ctx, &node->u.ctf_expression.right, ctx->ctf_tc->uuid);
3793 if (ret) {
3794 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Invalid trace's `uuid` attribute.");
3795 goto error;
3796 }
3797
3798 ctx->ctf_tc->is_uuid_set = true;
3799 _SET(set, _TRACE_UUID_SET);
3800 } else if (strcmp(left, "byte_order") == 0) {
3801 /* Default byte order is already known at this stage */
3802 if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) {
3803 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "byte_order", "trace");
3804 ret = -EPERM;
3805 goto error;
3806 }
3807
3808 BT_ASSERT(ctx->ctf_tc->default_byte_order != CTF_BYTE_ORDER_UNKNOWN);
3809 _SET(set, _TRACE_BYTE_ORDER_SET);
3810 } else if (strcmp(left, "packet.header") == 0) {
3811 if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) {
3812 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate `packet.header` entry in trace.");
3813 ret = -EPERM;
3814 goto error;
3815 }
3816
3817 ret = visit_field_class_specifier_list(
3818 ctx, _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings),
3819 &ctx->ctf_tc->packet_header_fc);
3820 if (ret) {
3821 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3822 "Cannot create trace's packet header field class.");
3823 goto error;
3824 }
3825
3826 BT_ASSERT(ctx->ctf_tc->packet_header_fc);
3827 _SET(set, _TRACE_PACKET_HEADER_SET);
3828 } else {
3829 _BT_COMP_LOGW_NODE(node,
3830 "Unknown attribute in stream class: "
3831 "attr-name=\"%s\"",
3832 left);
3833 }
3834
3835 g_free(left);
3836 left = NULL;
3837 break;
3838 }
3839 default:
3840 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unknown expression in trace.");
3841 ret = -EINVAL;
3842 goto error;
3843 }
3844
3845 return 0;
e98a2d6e
PP
3846
3847error:
4164020e
SM
3848 g_free(left);
3849 return ret;
e98a2d6e
PP
3850}
3851
4164020e 3852static int visit_trace_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
e98a2d6e 3853{
4164020e
SM
3854 int ret = 0;
3855 int set = 0;
3856 struct ctf_node *iter;
3857 struct bt_list_head *decl_list = &node->u.trace.declaration_list;
3858
3859 if (node->visited) {
3860 goto end;
3861 }
3862
3863 node->visited = TRUE;
3864
3865 if (ctx->is_trace_visited) {
3866 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate trace (`trace` block).");
3867 ret = -EEXIST;
3868 goto error;
3869 }
3870
3871 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3872
3873 bt_list_for_each_entry (iter, decl_list, siblings) {
3874 ret = visit_trace_decl_entry(ctx, iter, &set);
3875 if (ret) {
3876 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
3877 "Cannot visit trace's entry (`trace` block): "
3878 "ret=%d",
3879 ret);
3880 ctx_pop_scope(ctx);
3881 goto error;
3882 }
3883 }
3884
3885 ctx_pop_scope(ctx);
3886
3887 if (!_IS_SET(&set, _TRACE_MAJOR_SET)) {
3888 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3889 "Missing `major` attribute in trace (`trace` block).");
3890 ret = -EPERM;
3891 goto error;
3892 }
3893
3894 if (!_IS_SET(&set, _TRACE_MINOR_SET)) {
3895 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3896 "Missing `minor` attribute in trace (`trace` block).");
3897 ret = -EPERM;
3898 goto error;
3899 }
3900
3901 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
3902 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3903 "Missing `byte_order` attribute in trace (`trace` block).");
3904 ret = -EPERM;
3905 goto error;
3906 }
3907
3908 ctx->is_trace_visited = true;
e98a2d6e
PP
3909
3910end:
4164020e 3911 return 0;
e98a2d6e
PP
3912
3913error:
4164020e 3914 return ret;
e98a2d6e
PP
3915}
3916
4164020e 3917static int visit_env(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
e98a2d6e 3918{
4164020e
SM
3919 int ret = 0;
3920 char *left = NULL;
3921 struct ctf_node *entry_node;
3922 struct bt_list_head *decl_list = &node->u.env.declaration_list;
3923
3924 if (node->visited) {
3925 goto end;
3926 }
3927
3928 node->visited = TRUE;
3929
3930 bt_list_for_each_entry (entry_node, decl_list, siblings) {
3931 struct bt_list_head *right_head = &entry_node->u.ctf_expression.right;
3932
3933 if (entry_node->type != NODE_CTF_EXPRESSION) {
3934 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
3935 "Wrong expression in environment entry: "
3936 "node-type=%d",
3937 entry_node->type);
3938 ret = -EPERM;
3939 goto error;
3940 }
3941
3942 left = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.left);
3943 if (!left) {
3944 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Cannot get environment entry's name.");
3945 ret = -EINVAL;
3946 goto error;
3947 }
3948
3949 if (is_unary_string(right_head)) {
3950 char *right = ctf_ast_concatenate_unary_strings(right_head);
3951
3952 if (!right) {
3953 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3954 entry_node,
3955 "Unexpected unary expression for environment entry's value: "
3956 "name=\"%s\"",
3957 left);
3958 ret = -EINVAL;
3959 goto error;
3960 }
3961
3962 if (strcmp(left, "tracer_name") == 0) {
3963 if (strncmp(right, "lttng", 5) == 0) {
3964 BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: "
3965 "tracer-name=\"%s\"",
3966 left, right);
3967 ctx->is_lttng = true;
3968 }
3969 }
3970
3971 ctf_trace_class_append_env_entry(ctx->ctf_tc, left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR,
3972 right, 0);
3973 g_free(right);
3974 } else if (is_unary_unsigned(right_head) || is_unary_signed(right_head)) {
3975 int64_t v;
3976
3977 if (is_unary_unsigned(right_head)) {
3978 ret = get_unary_unsigned(ctx, right_head, (uint64_t *) &v);
3979 } else {
3980 ret = get_unary_signed(right_head, &v);
3981 }
3982 if (ret) {
3983 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
3984 entry_node,
3985 "Unexpected unary expression for environment entry's value: "
3986 "name=\"%s\"",
3987 left);
3988 ret = -EINVAL;
3989 goto error;
3990 }
3991
3992 ctf_trace_class_append_env_entry(ctx->ctf_tc, left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT,
3993 NULL, v);
3994 } else {
3995 _BT_COMP_LOGW_NODE(entry_node,
3996 "Environment entry has unknown type: "
3997 "name=\"%s\"",
3998 left);
3999 }
4000
4001 g_free(left);
4002 left = NULL;
4003 }
e98a2d6e
PP
4004
4005end:
4164020e 4006 return 0;
e98a2d6e
PP
4007
4008error:
4164020e
SM
4009 g_free(left);
4010 return ret;
e98a2d6e
PP
4011}
4012
4164020e 4013static int set_trace_byte_order(struct ctf_visitor_generate_ir *ctx, struct ctf_node *trace_node)
e98a2d6e 4014{
4164020e
SM
4015 int ret = 0;
4016 int set = 0;
4017 char *left = NULL;
4018 struct ctf_node *node;
4019 struct bt_list_head *decl_list = &trace_node->u.trace.declaration_list;
4020
4021 bt_list_for_each_entry (node, decl_list, siblings) {
4022 if (node->type == NODE_CTF_EXPRESSION) {
4023 struct ctf_node *right_node;
4024
4025 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
4026 if (!left) {
4027 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
4028 ret = -EINVAL;
4029 goto error;
4030 }
4031
4032 if (strcmp(left, "byte_order") == 0) {
4033 enum ctf_byte_order bo;
4034
4035 if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
4036 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "byte_order", "trace");
4037 ret = -EPERM;
4038 goto error;
4039 }
4040
4041 _SET(&set, _TRACE_BYTE_ORDER_SET);
4042 right_node =
4043 _BT_LIST_FIRST_ENTRY(&node->u.ctf_expression.right, struct ctf_node, siblings);
4044 bo = byte_order_from_unary_expr(ctx, right_node);
4045 if (bo == CTF_BYTE_ORDER_UNKNOWN) {
4046 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4047 node, "Invalid `byte_order` attribute in trace (`trace` block): "
4048 "expecting `le`, `be`, or `network`.");
4049 ret = -EINVAL;
4050 goto error;
4051 } else if (bo == CTF_BYTE_ORDER_DEFAULT) {
4052 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4053 node, "Invalid `byte_order` attribute in trace (`trace` block): "
4054 "cannot be set to `native` here.");
4055 ret = -EPERM;
4056 goto error;
4057 }
4058
4059 ctx->ctf_tc->default_byte_order = bo;
4060 }
4061
4062 g_free(left);
4063 left = NULL;
4064 }
4065 }
4066
4067 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
4068 _BT_COMP_LOGE_APPEND_CAUSE_NODE(trace_node,
4069 "Missing `byte_order` attribute in trace (`trace` block).");
4070 ret = -EINVAL;
4071 goto error;
4072 }
4073
4074 return 0;
e98a2d6e
PP
4075
4076error:
4164020e
SM
4077 g_free(left);
4078 return ret;
e98a2d6e
PP
4079}
4080
4164020e
SM
4081static int visit_clock_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *entry_node,
4082 struct ctf_clock_class *clock, int *set, int64_t *offset_seconds,
4083 uint64_t *offset_cycles)
e98a2d6e 4084{
4164020e
SM
4085 int ret = 0;
4086 char *left = NULL;
4087
4088 if (entry_node->type != NODE_CTF_EXPRESSION) {
4089 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Unexpected node type: node-type=%d",
4090 entry_node->type);
4091 ret = -EPERM;
4092 goto error;
4093 }
4094
4095 left = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.left);
4096 if (!left) {
4097 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Cannot concatenate unary strings.");
4098 ret = -EINVAL;
4099 goto error;
4100 }
4101
4102 if (strcmp(left, "name") == 0) {
4103 char *right;
4104
4105 if (_IS_SET(set, _CLOCK_NAME_SET)) {
4106 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "name", "clock class");
4107 ret = -EPERM;
4108 goto error;
4109 }
4110
4111 right = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.right);
4112 if (!right) {
4113 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4114 entry_node, "Unexpected unary expression for clock class's `name` attribute.");
4115 ret = -EINVAL;
4116 goto error;
4117 }
4118
4119 g_string_assign(clock->name, right);
4120 g_free(right);
4121 _SET(set, _CLOCK_NAME_SET);
4122 } else if (strcmp(left, "uuid") == 0) {
4123 bt_uuid_t uuid;
4124
4125 if (_IS_SET(set, _CLOCK_UUID_SET)) {
4126 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "uuid", "clock class");
4127 ret = -EPERM;
4128 goto error;
4129 }
4130
4131 ret = get_unary_uuid(ctx, &entry_node->u.ctf_expression.right, uuid);
4132 if (ret) {
4133 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Invalid clock class's `uuid` attribute.");
4134 goto error;
4135 }
4136
4137 clock->has_uuid = true;
4138 bt_uuid_copy(clock->uuid, uuid);
4139 _SET(set, _CLOCK_UUID_SET);
4140 } else if (strcmp(left, "description") == 0) {
4141 char *right;
4142
4143 if (_IS_SET(set, _CLOCK_DESCRIPTION_SET)) {
4144 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "description", "clock class");
4145 ret = -EPERM;
4146 goto error;
4147 }
4148
4149 right = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.right);
4150 if (!right) {
4151 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4152 entry_node,
4153 "Unexpected unary expression for clock class's `description` attribute.");
4154 ret = -EINVAL;
4155 goto error;
4156 }
4157
4158 g_string_assign(clock->description, right);
4159 g_free(right);
4160 _SET(set, _CLOCK_DESCRIPTION_SET);
4161 } else if (strcmp(left, "freq") == 0) {
4162 uint64_t freq = UINT64_C(-1);
4163
4164 if (_IS_SET(set, _CLOCK_FREQ_SET)) {
4165 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "freq", "clock class");
4166 ret = -EPERM;
4167 goto error;
4168 }
4169
4170 ret = get_unary_unsigned(ctx, &entry_node->u.ctf_expression.right, &freq);
4171 if (ret) {
4172 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4173 entry_node, "Unexpected unary expression for clock class's `freq` attribute.");
4174 ret = -EINVAL;
4175 goto error;
4176 }
4177
4178 if (freq == UINT64_C(-1) || freq == 0) {
4179 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4180 "Invalid clock class frequency: freq=%" PRIu64, freq);
4181 ret = -EINVAL;
4182 goto error;
4183 }
4184
4185 clock->frequency = freq;
4186 _SET(set, _CLOCK_FREQ_SET);
4187 } else if (strcmp(left, "precision") == 0) {
4188 uint64_t precision;
4189
4190 if (_IS_SET(set, _CLOCK_PRECISION_SET)) {
4191 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "precision", "clock class");
4192 ret = -EPERM;
4193 goto error;
4194 }
4195
4196 ret = get_unary_unsigned(ctx, &entry_node->u.ctf_expression.right, &precision);
4197 if (ret) {
4198 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4199 entry_node, "Unexpected unary expression for clock class's `precision` attribute.");
4200 ret = -EINVAL;
4201 goto error;
4202 }
4203
4204 clock->precision = precision;
4205 _SET(set, _CLOCK_PRECISION_SET);
4206 } else if (strcmp(left, "offset_s") == 0) {
4207 if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) {
4208 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "offset_s", "clock class");
4209 ret = -EPERM;
4210 goto error;
4211 }
4212
4213 ret = get_unary_signed(&entry_node->u.ctf_expression.right, offset_seconds);
4214 if (ret) {
4215 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4216 entry_node, "Unexpected unary expression for clock class's `offset_s` attribute.");
4217 ret = -EINVAL;
4218 goto error;
4219 }
4220
4221 _SET(set, _CLOCK_OFFSET_S_SET);
4222 } else if (strcmp(left, "offset") == 0) {
4223 if (_IS_SET(set, _CLOCK_OFFSET_SET)) {
4224 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "offset", "clock class");
4225 ret = -EPERM;
4226 goto error;
4227 }
4228
4229 ret = get_unary_unsigned(ctx, &entry_node->u.ctf_expression.right, offset_cycles);
4230 if (ret) {
4231 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4232 entry_node, "Unexpected unary expression for clock class's `offset` attribute.");
4233 ret = -EINVAL;
4234 goto error;
4235 }
4236
4237 _SET(set, _CLOCK_OFFSET_SET);
4238 } else if (strcmp(left, "absolute") == 0) {
4239 struct ctf_node *right;
4240
4241 if (_IS_SET(set, _CLOCK_ABSOLUTE_SET)) {
4242 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "absolute", "clock class");
4243 ret = -EPERM;
4244 goto error;
4245 }
4246
4247 right =
4248 _BT_LIST_FIRST_ENTRY(&entry_node->u.ctf_expression.right, struct ctf_node, siblings);
4249 ret = get_boolean(ctx, right);
4250 if (ret < 0) {
4251 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4252 entry_node, "Unexpected unary expression for clock class's `absolute` attribute.");
4253 ret = -EINVAL;
4254 goto error;
4255 }
4256
4257 clock->is_absolute = ret;
4258 _SET(set, _CLOCK_ABSOLUTE_SET);
4259 } else {
4260 _BT_COMP_LOGW_NODE(entry_node, "Unknown attribute in clock class: attr-name=\"%s\"", left);
4261 }
4262
4263 g_free(left);
4264 left = NULL;
4265 return 0;
e98a2d6e
PP
4266
4267error:
4164020e
SM
4268 g_free(left);
4269 return ret;
e98a2d6e
PP
4270}
4271
4164020e 4272static inline uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns)
92540773 4273{
4164020e 4274 uint64_t cycles;
92540773 4275
4164020e
SM
4276 /* 1GHz */
4277 if (frequency == UINT64_C(1000000000)) {
4278 cycles = ns;
4279 } else {
4280 cycles = (uint64_t) (((double) ns * (double) frequency) / 1e9);
4281 }
92540773 4282
4164020e 4283 return cycles;
92540773
JD
4284}
4285
4164020e
SM
4286static void calibrate_clock_class_offsets(int64_t *offset_seconds, uint64_t *offset_cycles,
4287 uint64_t freq)
44c440bc 4288{
4164020e
SM
4289 if (*offset_cycles >= freq) {
4290 const uint64_t s_in_offset_cycles = *offset_cycles / freq;
44c440bc 4291
4164020e
SM
4292 *offset_seconds += (int64_t) s_in_offset_cycles;
4293 *offset_cycles -= (s_in_offset_cycles * freq);
4294 }
44c440bc
PP
4295}
4296
4164020e
SM
4297static void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir *ctx,
4298 struct ctf_clock_class *clock)
c0aa240b 4299{
4164020e
SM
4300 if (ctx->decoder_config.force_clock_class_origin_unix_epoch) {
4301 clock->is_absolute = true;
4302 }
c0aa240b 4303
4164020e 4304 return;
c0aa240b
FD
4305}
4306
4164020e
SM
4307static void apply_clock_class_offset(struct ctf_visitor_generate_ir *ctx,
4308 struct ctf_clock_class *clock)
92540773 4309{
4164020e
SM
4310 uint64_t freq;
4311 int64_t offset_s_to_apply = ctx->decoder_config.clock_class_offset_s;
4312 uint64_t offset_ns_to_apply;
4313 int64_t cur_offset_s;
4314 uint64_t cur_offset_cycles;
4315
4316 if (ctx->decoder_config.clock_class_offset_s == 0 &&
4317 ctx->decoder_config.clock_class_offset_ns == 0) {
4318 goto end;
4319 }
4320
4321 /* Transfer nanoseconds to seconds as much as possible */
4322 if (ctx->decoder_config.clock_class_offset_ns < 0) {
4323 const int64_t abs_ns = -ctx->decoder_config.clock_class_offset_ns;
4324 const int64_t abs_extra_s = abs_ns / INT64_C(1000000000) + 1;
4325 const int64_t extra_s = -abs_extra_s;
4326 const int64_t offset_ns =
4327 ctx->decoder_config.clock_class_offset_ns - (extra_s * INT64_C(1000000000));
4328
4329 BT_ASSERT(offset_ns > 0);
4330 offset_ns_to_apply = (uint64_t) offset_ns;
4331 offset_s_to_apply += extra_s;
4332 } else {
4333 const int64_t extra_s = ctx->decoder_config.clock_class_offset_ns / INT64_C(1000000000);
4334 const int64_t offset_ns =
4335 ctx->decoder_config.clock_class_offset_ns - (extra_s * INT64_C(1000000000));
4336
4337 BT_ASSERT(offset_ns >= 0);
4338 offset_ns_to_apply = (uint64_t) offset_ns;
4339 offset_s_to_apply += extra_s;
4340 }
4341
4342 freq = clock->frequency;
4343 cur_offset_s = clock->offset_seconds;
4344 cur_offset_cycles = clock->offset_cycles;
4345
4346 /* Apply offsets */
4347 cur_offset_s += offset_s_to_apply;
4348 cur_offset_cycles += cycles_from_ns(freq, offset_ns_to_apply);
4349
4350 /*
4351 * Recalibrate offsets because the part in cycles can be greater
4352 * than the frequency at this point.
4353 */
4354 calibrate_clock_class_offsets(&cur_offset_s, &cur_offset_cycles, freq);
4355
4356 /* Set final offsets */
4357 clock->offset_seconds = cur_offset_s;
4358 clock->offset_cycles = cur_offset_cycles;
92540773
JD
4359
4360end:
4164020e 4361 return;
92540773
JD
4362}
4363
4164020e 4364static int visit_clock_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *clock_node)
e98a2d6e 4365{
4164020e
SM
4366 int ret = 0;
4367 int set = 0;
4368 struct ctf_clock_class *clock;
4369 struct ctf_node *entry_node;
4370 struct bt_list_head *decl_list = &clock_node->u.clock.declaration_list;
4371 const char *clock_class_name;
4372 int64_t offset_seconds = 0;
4373 uint64_t offset_cycles = 0;
4374 uint64_t freq;
4375
4376 if (clock_node->visited) {
4377 return 0;
4378 }
4379
4380 clock_node->visited = TRUE;
4381
4382 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4383 clock = ctf_clock_class_create();
4384 if (!clock) {
4385 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node, "Cannot create default clock class.");
4386 ret = -ENOMEM;
4387 goto end;
4388 }
4389
4390 bt_list_for_each_entry (entry_node, decl_list, siblings) {
4391 ret = visit_clock_decl_entry(ctx, entry_node, clock, &set, &offset_seconds, &offset_cycles);
4392 if (ret) {
4393 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Cannot visit clock class's entry: ret=%d",
4394 ret);
4395 goto end;
4396 }
4397 }
4398
4399 if (!_IS_SET(&set, _CLOCK_NAME_SET)) {
4400 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node, "Missing `name` attribute in clock class.");
4401 ret = -EPERM;
4402 goto end;
4403 }
4404
4405 clock_class_name = clock->name->str;
4406 BT_ASSERT(clock_class_name);
4407 if (ctx->is_lttng && strcmp(clock_class_name, "monotonic") == 0) {
4408 /*
4409 * Old versions of LTTng forgot to set its clock class
4410 * as absolute, even if it is. This is important because
4411 * it's a condition to be able to sort messages
4412 * from different sources.
4413 */
4414 clock->is_absolute = true;
4415 }
4416
4417 /*
4418 * Adjust offsets so that the part in cycles is less than the
4419 * frequency (move to the part in seconds).
4420 */
4421 freq = clock->frequency;
4422 calibrate_clock_class_offsets(&offset_seconds, &offset_cycles, freq);
4423 BT_ASSERT(offset_cycles < clock->frequency);
4424 clock->offset_seconds = offset_seconds;
4425 clock->offset_cycles = offset_cycles;
4426 apply_clock_class_offset(ctx, clock);
4427 apply_clock_class_is_absolute(ctx, clock);
4428 g_ptr_array_add(ctx->ctf_tc->clock_classes, clock);
4429 clock = NULL;
e98a2d6e 4430
44c440bc 4431end:
4164020e
SM
4432 if (clock) {
4433 ctf_clock_class_destroy(clock);
4434 }
0f2d58c9 4435
4164020e 4436 return ret;
e98a2d6e
PP
4437}
4438
4164020e 4439static int visit_root_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *root_decl_node)
e98a2d6e 4440{
4164020e
SM
4441 int ret = 0;
4442
4443 if (root_decl_node->visited) {
4444 goto end;
4445 }
4446
4447 root_decl_node->visited = TRUE;
4448
4449 switch (root_decl_node->type) {
4450 case NODE_TYPEDEF:
4451 ret =
4452 visit_field_class_def(ctx, root_decl_node->u.field_class_def.field_class_specifier_list,
4453 &root_decl_node->u.field_class_def.field_class_declarators);
4454 if (ret) {
4455 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node,
4456 "Cannot add field class found in root scope.");
4457 goto end;
4458 }
4459 break;
4460 case NODE_TYPEALIAS:
4461 ret = visit_field_class_alias(ctx, root_decl_node->u.field_class_alias.target,
4462 root_decl_node->u.field_class_alias.alias);
4463 if (ret) {
4464 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node,
4465 "Cannot add field class alias found in root scope.");
4466 goto end;
4467 }
4468 break;
4469 case NODE_TYPE_SPECIFIER_LIST:
4470 {
4471 struct ctf_field_class *decl = NULL;
4472
4473 /*
4474 * Just add the field class specifier to the root
4475 * declaration scope. Put local reference.
4476 */
4477 ret = visit_field_class_specifier_list(ctx, root_decl_node, &decl);
4478 if (ret) {
4479 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node,
4480 "Cannot visit root scope's field class: "
4481 "ret=%d",
4482 ret);
4483 BT_ASSERT(!decl);
4484 goto end;
4485 }
4486
4487 ctf_field_class_destroy(decl);
4488 decl = NULL;
4489 break;
4490 }
4491 default:
4492 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node, "Unexpected node type: node-type=%d",
4493 root_decl_node->type);
4494 ret = -EPERM;
4495 goto end;
4496 }
e98a2d6e
PP
4497
4498end:
4164020e 4499 return ret;
e98a2d6e
PP
4500}
4501
1e649dff 4502BT_HIDDEN
4164020e
SM
4503struct ctf_visitor_generate_ir *
4504ctf_visitor_generate_ir_create(const struct ctf_metadata_decoder_config *decoder_config)
e98a2d6e 4505{
4164020e 4506 struct ctf_visitor_generate_ir *ctx = NULL;
e98a2d6e 4507
4164020e
SM
4508 /* Create visitor's context */
4509 ctx = ctx_create(decoder_config);
4510 if (!ctx) {
4511 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, decoder_config->log_level, decoder_config->self_comp,
4512 "Cannot create visitor's context.");
4513 goto error;
4514 }
e98a2d6e 4515
4164020e 4516 goto end;
1e649dff
PP
4517
4518error:
4164020e
SM
4519 ctx_destroy(ctx);
4520 ctx = NULL;
1e649dff
PP
4521
4522end:
4164020e 4523 return ctx;
1e649dff
PP
4524}
4525
4526BT_HIDDEN
4527void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir *visitor)
4528{
4164020e 4529 ctx_destroy(visitor);
1e649dff
PP
4530}
4531
4532BT_HIDDEN
4164020e 4533bt_trace_class *ctf_visitor_generate_ir_get_ir_trace_class(struct ctf_visitor_generate_ir *ctx)
1e649dff 4534{
4164020e 4535 BT_ASSERT_DBG(ctx);
41693723 4536
4164020e
SM
4537 if (ctx->trace_class) {
4538 bt_trace_class_get_ref(ctx->trace_class);
4539 }
41693723 4540
4164020e 4541 return ctx->trace_class;
1e649dff
PP
4542}
4543
44c440bc 4544BT_HIDDEN
4164020e
SM
4545struct ctf_trace_class *
4546ctf_visitor_generate_ir_borrow_ctf_trace_class(struct ctf_visitor_generate_ir *ctx)
44c440bc 4547{
4164020e
SM
4548 BT_ASSERT_DBG(ctx);
4549 BT_ASSERT_DBG(ctx->ctf_tc);
4550 return ctx->ctf_tc;
44c440bc
PP
4551}
4552
1e649dff 4553BT_HIDDEN
4164020e 4554int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
1e649dff 4555{
4164020e
SM
4556 int ret = 0;
4557
4558 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
4559
4560 switch (node->type) {
4561 case NODE_ROOT:
4562 {
4563 struct ctf_node *iter;
4564 bool got_trace_decl = false;
4565
4566 /*
4567 * The first thing we need is the native byte order of
4568 * the trace block, because early class aliases can have
4569 * a `byte_order` attribute set to `native`. If we don't
4570 * have the native byte order yet, and we don't have any
4571 * trace block yet, then fail with EINCOMPLETE.
4572 */
4573 if (ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_UNKNOWN) {
4574 bt_list_for_each_entry (iter, &node->u.root.trace, siblings) {
4575 if (got_trace_decl) {
4576 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate trace (`trace` block).");
4577 ret = -1;
4578 goto end;
4579 }
4580
4581 ret = set_trace_byte_order(ctx, iter);
4582 if (ret) {
4583 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
4584 "Cannot set trace's native byte order: "
4585 "ret=%d",
4586 ret);
4587 goto end;
4588 }
4589
4590 got_trace_decl = true;
4591 }
4592
4593 if (!got_trace_decl) {
4594 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
4595 ret = -EINCOMPLETE;
4596 goto end;
4597 }
4598 }
4599
4600 BT_ASSERT(ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_LITTLE ||
4601 ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_BIG);
4602 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4603
4604 /* Environment */
4605 bt_list_for_each_entry (iter, &node->u.root.env, siblings) {
4606 ret = visit_env(ctx, iter);
4607 if (ret) {
4608 _BT_COMP_LOGE_APPEND_CAUSE_NODE(
4609 iter,
4610 "Cannot visit trace's environment (`env` block) entry: "
4611 "ret=%d",
4612 ret);
4613 goto end;
4614 }
4615 }
4616
4617 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4618
4619 /*
4620 * Visit clock blocks.
4621 */
4622 bt_list_for_each_entry (iter, &node->u.root.clock, siblings) {
4623 ret = visit_clock_decl(ctx, iter);
4624 if (ret) {
4625 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit clock class: ret=%d", ret);
4626 goto end;
4627 }
4628 }
4629
4630 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4631
4632 /*
4633 * Visit root declarations next, as they can be used by any
4634 * following entity.
4635 */
4636 bt_list_for_each_entry (iter, &node->u.root.declaration_list, siblings) {
4637 ret = visit_root_decl(ctx, iter);
4638 if (ret) {
4639 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit root entry: ret=%d", ret);
4640 goto end;
4641 }
4642 }
4643
4644 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4645
4646 /* Callsite blocks are not supported */
4647 bt_list_for_each_entry (iter, &node->u.root.callsite, siblings) {
4648 _BT_COMP_LOGW_NODE(iter, "\"callsite\" blocks are not supported as of this version.");
4649 }
4650
4651 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4652
4653 /* Trace */
4654 bt_list_for_each_entry (iter, &node->u.root.trace, siblings) {
4655 ret = visit_trace_decl(ctx, iter);
4656 if (ret) {
4657 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
4658 "Cannot visit trace (`trace` block): "
4659 "ret=%d",
4660 ret);
4661 goto end;
4662 }
4663 }
4664
4665 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4666
4667 /* Streams */
4668 bt_list_for_each_entry (iter, &node->u.root.stream, siblings) {
4669 ret = visit_stream_decl(ctx, iter);
4670 if (ret) {
4671 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit stream class: ret=%d", ret);
4672 goto end;
4673 }
4674 }
4675
4676 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4677
4678 /* Events */
4679 bt_list_for_each_entry (iter, &node->u.root.event, siblings) {
4680 ret = visit_event_decl(ctx, iter);
4681 if (ret) {
4682 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit event class: ret=%d", ret);
4683 goto end;
4684 }
4685 }
4686
4687 BT_ASSERT(ctx->current_scope && !ctx->current_scope->parent_scope);
4688 break;
4689 }
4690 default:
4691 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unexpected node type: node-type=%d", node->type);
4692 ret = -EINVAL;
4693 goto end;
4694 }
4695
4696 /* Update default clock classes */
4697 ret = ctf_trace_class_update_default_clock_classes(ctx->ctf_tc, &ctx->log_cfg);
4698 if (ret) {
4699 ret = -EINVAL;
4700 goto end;
4701 }
4702
4703 /* Update trace class meanings */
4704 ret = ctf_trace_class_update_meanings(ctx->ctf_tc);
4705 if (ret) {
4706 ret = -EINVAL;
4707 goto end;
4708 }
4709
4710 /* Update stream class configuration */
4711 ret = ctf_trace_class_update_stream_class_config(ctx->ctf_tc);
4712 if (ret) {
4713 ret = -EINVAL;
4714 goto end;
4715 }
4716
4717 /* Update text arrays and sequences */
4718 ret = ctf_trace_class_update_text_array_sequence(ctx->ctf_tc);
4719 if (ret) {
4720 ret = -EINVAL;
4721 goto end;
4722 }
4723
4724 /* Update structure/array/sequence alignments */
4725 ret = ctf_trace_class_update_alignments(ctx->ctf_tc);
4726 if (ret) {
4727 ret = -EINVAL;
4728 goto end;
4729 }
4730
4731 /* Resolve sequence lengths and variant tags */
4732 ret = ctf_trace_class_resolve_field_classes(ctx->ctf_tc, &ctx->log_cfg);
4733 if (ret) {
4734 ret = -EINVAL;
4735 goto end;
4736 }
4737
4738 if (ctx->trace_class) {
4739 /*
4740 * Update "in IR" for field classes.
4741 *
4742 * If we have no IR trace class, then we'll have no way
4743 * to create IR fields anyway, so we leave all the
4744 * `in_ir` members false.
4745 */
4746 ret = ctf_trace_class_update_in_ir(ctx->ctf_tc);
4747 if (ret) {
4748 ret = -EINVAL;
4749 goto end;
4750 }
4751 }
4752
4753 /* Update saved value indexes */
4754 ret = ctf_trace_class_update_value_storing_indexes(ctx->ctf_tc);
4755 if (ret) {
4756 ret = -EINVAL;
4757 goto end;
4758 }
4759
4760 /* Validate what we have so far */
4761 ret = ctf_trace_class_validate(ctx->ctf_tc, &ctx->log_cfg);
4762 if (ret) {
4763 ret = -EINVAL;
4764 goto end;
4765 }
4766
4767 /*
4768 * If there are fields which are not related to the CTF format
4769 * itself in the packet header and in event header field
4770 * classes, warn about it because they are never translated.
4771 */
4772 ctf_trace_class_warn_meaningless_header_fields(ctx->ctf_tc, &ctx->log_cfg);
4773
4774 if (ctx->trace_class) {
4775 /* Copy new CTF metadata -> new IR metadata */
4776 ret = ctf_trace_class_translate(ctx->log_cfg.self_comp, ctx->trace_class, ctx->ctf_tc);
4777 if (ret) {
4778 ret = -EINVAL;
4779 goto end;
4780 }
4781 }
e98a2d6e 4782
1e649dff 4783end:
4164020e 4784 return ret;
e98a2d6e 4785}
This page took 0.327765 seconds and 4 git commands to generate.