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