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