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