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