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