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