ctf: compile plugin as C++
[babeltrace.git] / src / plugins / ctf / common / metadata / visitor-generate-ir.cpp
CommitLineData
e98a2d6e 1/*
0235b0db 2 * SPDX-License-Identifier: MIT
e98a2d6e 3 *
0235b0db
MJ
4 * Copyright 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * Copyright 2015-2018 Philippe Proulx <philippe.proulx@efficios.com>
e98a2d6e 6 *
0235b0db 7 * Common Trace Format metadata visitor (generates CTF IR objects).
e98a2d6e
PP
8 */
9
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
087cd0f5
SM
31#include "logging.hpp"
32#include "scanner.hpp"
33#include "ast.hpp"
34#include "decoder.hpp"
35#include "ctf-meta.hpp"
36#include "ctf-meta-visitors.hpp"
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) {
087cd0f5 318 decl = (ctf_field_class *) 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{
087cd0f5
SM
372 return ctf_field_class_as_enum(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{
087cd0f5
SM
391 return ctf_field_class_as_struct(ctx_decl_scope_lookup_prefix_alias(ctx, scope,
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{
087cd0f5
SM
410 return ctf_field_class_as_variant(ctx_decl_scope_lookup_prefix_alias(ctx, scope,
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,
087cd0f5 468 name, 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,
087cd0f5 485 name, &decl->base.base.base);
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,
087cd0f5 502 name, &decl->base);
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,
087cd0f5 519 name, &decl->base);
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 =
087cd0f5 1213 ctf_field_class_as_int(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 1284 nested_decl = NULL;
087cd0f5 1285 decl = &array_decl->base.base;
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 1342 nested_decl = NULL;
087cd0f5 1343 decl = &array_decl->base.base;
44c440bc 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);
087cd0f5 1351 decl = &seq_decl->base.base;
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 1531 struct ctf_field_class_variant *var_fc =
087cd0f5 1532 ctf_field_class_as_variant(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) {
087cd0f5
SM
1589 struct ctf_field_class_variant *var_fc =
1590 ctf_field_class_as_variant(class_decl);
44c440bc 1591
5cd6d0e5 1592 if (var_fc->tag_path.path->len == 0) {
50f6fce8 1593 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target,
5cd6d0e5 1594 "Type definition of untagged variant field class is not allowed.");
e98a2d6e
PP
1595 ret = -EPERM;
1596 goto end;
1597 }
1598 }
1599
1600 /*
1601 * The semantic validator does not check whether the target is
1602 * abstract or not (if it has an identifier). Check it here.
1603 */
1604 if (qdummy_field_name != 0) {
50f6fce8 1605 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target,
28973adf 1606 "Expecting empty identifier: id=\"%s\"",
08da4f77 1607 g_quark_to_string(qdummy_field_name));
e98a2d6e
PP
1608 ret = -EINVAL;
1609 goto end;
1610 }
1611
1612 /* Create alias identifier */
5cd6d0e5 1613 node = _BT_LIST_FIRST_ENTRY(&alias->u.field_class_alias_name.field_class_declarators,
e98a2d6e 1614 struct ctf_node, siblings);
5cd6d0e5
PP
1615 qalias = create_class_alias_identifier(ctx,
1616 alias->u.field_class_alias_name.field_class_specifier_list, node);
0746848c 1617 ret = ctx_decl_scope_register_alias(ctx, ctx->current_scope,
5cd6d0e5 1618 g_quark_to_string(qalias), class_decl);
e98a2d6e 1619 if (ret) {
50f6fce8 1620 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 1621 "Cannot register class alias: name=\"%s\"",
e98a2d6e
PP
1622 g_quark_to_string(qalias));
1623 goto end;
1624 }
1625
1626end:
5cd6d0e5
PP
1627 ctf_field_class_destroy(class_decl);
1628 class_decl = NULL;
e98a2d6e
PP
1629 return ret;
1630}
1631
1632static
cf81cdae 1633int visit_struct_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *entry_node,
5cd6d0e5 1634 struct ctf_field_class_struct *struct_decl)
e98a2d6e
PP
1635{
1636 int ret = 0;
1637
1638 switch (entry_node->type) {
1639 case NODE_TYPEDEF:
5cd6d0e5
PP
1640 ret = visit_field_class_def(ctx,
1641 entry_node->u.field_class_def.field_class_specifier_list,
1642 &entry_node->u.field_class_def.field_class_declarators);
e98a2d6e 1643 if (ret) {
50f6fce8 1644 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
5cd6d0e5 1645 "Cannot add field class found in structure field class: ret=%d",
08da4f77 1646 ret);
e98a2d6e
PP
1647 goto end;
1648 }
1649 break;
1650 case NODE_TYPEALIAS:
5cd6d0e5
PP
1651 ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target,
1652 entry_node->u.field_class_alias.alias);
e98a2d6e 1653 if (ret) {
50f6fce8 1654 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
5cd6d0e5 1655 "Cannot add field class alias found in structure field class: ret=%d",
08da4f77 1656 ret);
e98a2d6e
PP
1657 goto end;
1658 }
1659 break;
1660 case NODE_STRUCT_OR_VARIANT_DECLARATION:
1661 /* Field */
1662 ret = visit_struct_decl_field(ctx, struct_decl,
1663 entry_node->u.struct_or_variant_declaration.
5cd6d0e5 1664 field_class_specifier_list,
e98a2d6e 1665 &entry_node->u.struct_or_variant_declaration.
5cd6d0e5 1666 field_class_declarators);
e98a2d6e
PP
1667 if (ret) {
1668 goto end;
1669 }
1670 break;
1671 default:
50f6fce8 1672 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 1673 "Unexpected node type: node-type=%d", entry_node->type);
e98a2d6e
PP
1674 ret = -EINVAL;
1675 goto end;
1676 }
1677
1678end:
1679 return ret;
1680}
1681
1682static
cf81cdae 1683int visit_variant_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *entry_node,
5cd6d0e5 1684 struct ctf_field_class_variant *variant_decl)
e98a2d6e
PP
1685{
1686 int ret = 0;
1687
1688 switch (entry_node->type) {
1689 case NODE_TYPEDEF:
5cd6d0e5
PP
1690 ret = visit_field_class_def(ctx,
1691 entry_node->u.field_class_def.field_class_specifier_list,
1692 &entry_node->u.field_class_def.field_class_declarators);
e98a2d6e 1693 if (ret) {
50f6fce8 1694 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
5cd6d0e5 1695 "Cannot add field class found in variant field class: ret=%d",
08da4f77 1696 ret);
e98a2d6e
PP
1697 goto end;
1698 }
1699 break;
1700 case NODE_TYPEALIAS:
5cd6d0e5
PP
1701 ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target,
1702 entry_node->u.field_class_alias.alias);
e98a2d6e 1703 if (ret) {
50f6fce8 1704 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
5cd6d0e5 1705 "Cannot add field class alias found in variant field class: ret=%d",
08da4f77 1706 ret);
e98a2d6e
PP
1707 goto end;
1708 }
1709 break;
1710 case NODE_STRUCT_OR_VARIANT_DECLARATION:
1711 /* Field */
1712 ret = visit_variant_decl_field(ctx, variant_decl,
1713 entry_node->u.struct_or_variant_declaration.
5cd6d0e5 1714 field_class_specifier_list,
e98a2d6e 1715 &entry_node->u.struct_or_variant_declaration.
5cd6d0e5 1716 field_class_declarators);
e98a2d6e
PP
1717 if (ret) {
1718 goto end;
1719 }
1720 break;
1721 default:
50f6fce8 1722 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 1723 "Unexpected node type: node-type=%d",
08da4f77 1724 entry_node->type);
e98a2d6e
PP
1725 ret = -EINVAL;
1726 goto end;
1727 }
1728
1729end:
1730 return ret;
1731}
1732
1733static
cf81cdae 1734int visit_struct_decl(struct ctf_visitor_generate_ir *ctx, const char *name,
44c440bc
PP
1735 struct bt_list_head *decl_list, int has_body,
1736 struct bt_list_head *min_align,
5cd6d0e5 1737 struct ctf_field_class_struct **struct_decl)
e98a2d6e
PP
1738{
1739 int ret = 0;
1740
44c440bc 1741 BT_ASSERT(struct_decl);
e98a2d6e
PP
1742 *struct_decl = NULL;
1743
1744 /* For named struct (without body), lookup in declaration scope */
1745 if (!has_body) {
e98a2d6e 1746 if (!name) {
50f6fce8 1747 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless structure field class: missing name.");
e98a2d6e
PP
1748 ret = -EPERM;
1749 goto error;
1750 }
1751
0746848c 1752 *struct_decl = ctx_decl_scope_lookup_struct(ctx, ctx->current_scope,
44c440bc 1753 name, -1, true);
e98a2d6e 1754 if (!*struct_decl) {
50f6fce8 1755 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find structure field class: name=\"struct %s\"",
08da4f77 1756 name);
e98a2d6e
PP
1757 ret = -EINVAL;
1758 goto error;
1759 }
e98a2d6e
PP
1760 } else {
1761 struct ctf_node *entry_node;
1762 uint64_t min_align_value = 0;
1763
1764 if (name) {
0746848c 1765 if (ctx_decl_scope_lookup_struct(ctx,
44c440bc 1766 ctx->current_scope, name, 1, false)) {
50f6fce8 1767 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Structure field class already declared in local scope: "
08da4f77 1768 "name=\"struct %s\"", name);
e98a2d6e
PP
1769 ret = -EINVAL;
1770 goto error;
1771 }
1772 }
1773
1774 if (!bt_list_empty(min_align)) {
0746848c
PP
1775 ret = get_unary_unsigned(ctx, min_align,
1776 &min_align_value);
e98a2d6e 1777 if (ret) {
50f6fce8 1778 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Unexpected unary expression for structure field class's `align` attribute: "
08da4f77 1779 "ret=%d", ret);
e98a2d6e
PP
1780 goto error;
1781 }
1782 }
1783
5cd6d0e5 1784 *struct_decl = ctf_field_class_struct_create();
44c440bc 1785 BT_ASSERT(*struct_decl);
e98a2d6e 1786
539fd01b 1787 if (min_align_value != 0) {
44c440bc 1788 (*struct_decl)->base.alignment = min_align_value;
539fd01b
JG
1789 }
1790
44c440bc 1791 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
e98a2d6e
PP
1792
1793 bt_list_for_each_entry(entry_node, decl_list, siblings) {
1794 ret = visit_struct_decl_entry(ctx, entry_node,
1795 *struct_decl);
1796 if (ret) {
50f6fce8 1797 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
5cd6d0e5 1798 "Cannot visit structure field class entry: "
28973adf 1799 "ret=%d", ret);
e98a2d6e
PP
1800 ctx_pop_scope(ctx);
1801 goto error;
1802 }
1803 }
1804
1805 ctx_pop_scope(ctx);
1806
1807 if (name) {
0746848c
PP
1808 ret = ctx_decl_scope_register_struct(ctx,
1809 ctx->current_scope, name, *struct_decl);
e98a2d6e 1810 if (ret) {
50f6fce8 1811 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register structure field class in declaration scope: "
08da4f77 1812 "name=\"struct %s\", ret=%d", name, ret);
e98a2d6e
PP
1813 goto error;
1814 }
1815 }
1816 }
1817
1818 return 0;
1819
1820error:
087cd0f5 1821 ctf_field_class_destroy(&(*struct_decl)->base);
44c440bc 1822 *struct_decl = NULL;
e98a2d6e
PP
1823 return ret;
1824}
1825
1826static
cf81cdae 1827int visit_variant_decl(struct ctf_visitor_generate_ir *ctx, const char *name,
e98a2d6e 1828 const char *tag, struct bt_list_head *decl_list,
5cd6d0e5 1829 int has_body, struct ctf_field_class_variant **variant_decl)
e98a2d6e
PP
1830{
1831 int ret = 0;
5cd6d0e5 1832 struct ctf_field_class_variant *untagged_variant_decl = NULL;
e98a2d6e 1833
44c440bc 1834 BT_ASSERT(variant_decl);
e98a2d6e
PP
1835 *variant_decl = NULL;
1836
1837 /* For named variant (without body), lookup in declaration scope */
1838 if (!has_body) {
e98a2d6e 1839 if (!name) {
50f6fce8 1840 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name.");
e98a2d6e
PP
1841 ret = -EPERM;
1842 goto error;
1843 }
1844
1845 untagged_variant_decl =
0746848c 1846 ctx_decl_scope_lookup_variant(ctx, ctx->current_scope,
44c440bc 1847 name, -1, true);
e98a2d6e 1848 if (!untagged_variant_decl) {
50f6fce8 1849 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find variant field class: name=\"variant %s\"",
08da4f77 1850 name);
e98a2d6e
PP
1851 ret = -EINVAL;
1852 goto error;
1853 }
e98a2d6e
PP
1854 } else {
1855 struct ctf_node *entry_node;
1856
1857 if (name) {
0746848c
PP
1858 if (ctx_decl_scope_lookup_variant(ctx,
1859 ctx->current_scope, name, 1, false)) {
50f6fce8 1860 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Variant field class already declared in local scope: "
08da4f77 1861 "name=\"variant %s\"", name);
e98a2d6e
PP
1862 ret = -EINVAL;
1863 goto error;
1864 }
1865 }
1866
5cd6d0e5 1867 untagged_variant_decl = ctf_field_class_variant_create();
44c440bc
PP
1868 BT_ASSERT(untagged_variant_decl);
1869 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
e98a2d6e
PP
1870
1871 bt_list_for_each_entry(entry_node, decl_list, siblings) {
1872 ret = visit_variant_decl_entry(ctx, entry_node,
1873 untagged_variant_decl);
1874 if (ret) {
50f6fce8 1875 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
5cd6d0e5 1876 "Cannot visit variant field class entry: "
28973adf 1877 "ret=%d", ret);
e98a2d6e
PP
1878 ctx_pop_scope(ctx);
1879 goto error;
1880 }
1881 }
1882
1883 ctx_pop_scope(ctx);
1884
1885 if (name) {
0746848c 1886 ret = ctx_decl_scope_register_variant(ctx,
e98a2d6e
PP
1887 ctx->current_scope, name,
1888 untagged_variant_decl);
1889 if (ret) {
50f6fce8 1890 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register variant field class in declaration scope: "
08da4f77 1891 "name=\"variant %s\", ret=%d", name, ret);
e98a2d6e
PP
1892 goto error;
1893 }
1894 }
1895 }
1896
1897 /*
1898 * If tagged, create tagged variant and return; otherwise
1899 * return untagged variant.
1900 */
1901 if (!tag) {
44c440bc
PP
1902 *variant_decl = untagged_variant_decl;
1903 untagged_variant_decl = NULL;
e98a2d6e
PP
1904 } else {
1905 /*
1906 * At this point, we have a fresh untagged variant; nobody
1907 * else owns it. Set its tag now.
1908 */
45c51519 1909 g_string_assign(untagged_variant_decl->tag_ref, tag);
44c440bc
PP
1910 *variant_decl = untagged_variant_decl;
1911 untagged_variant_decl = NULL;
e98a2d6e
PP
1912 }
1913
f6ccaed9
PP
1914 BT_ASSERT(!untagged_variant_decl);
1915 BT_ASSERT(*variant_decl);
e98a2d6e
PP
1916 return 0;
1917
1918error:
087cd0f5 1919 ctf_field_class_destroy(&untagged_variant_decl->base);
44c440bc 1920 untagged_variant_decl = NULL;
087cd0f5 1921 ctf_field_class_destroy(&(*variant_decl)->base);
44c440bc 1922 *variant_decl = NULL;
e98a2d6e
PP
1923 return ret;
1924}
1925
44c440bc
PP
1926struct uori {
1927 bool is_signed;
1928 union {
1929 uint64_t u;
1930 uint64_t i;
1931 } value;
1932};
1933
e98a2d6e 1934static
cf81cdae 1935int visit_enum_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *enumerator,
5cd6d0e5 1936 struct ctf_field_class_enum *enum_decl, struct uori *last)
e98a2d6e
PP
1937{
1938 int ret = 0;
1939 int nr_vals = 0;
1940 struct ctf_node *iter;
44c440bc
PP
1941 struct uori start = {
1942 .is_signed = false,
087cd0f5
SM
1943 .value = {
1944 .u = 0,
1945 },
44c440bc
PP
1946 };
1947 struct uori end = {
1948 .is_signed = false,
087cd0f5
SM
1949 .value = {
1950 .u = 0,
1951 },
44c440bc 1952 };
e98a2d6e
PP
1953 const char *label = enumerator->u.enumerator.id;
1954 struct bt_list_head *values = &enumerator->u.enumerator.values;
1955
1956 bt_list_for_each_entry(iter, values, siblings) {
44c440bc 1957 struct uori *target;
e98a2d6e
PP
1958
1959 if (iter->type != NODE_UNARY_EXPRESSION) {
50f6fce8 1960 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
5cd6d0e5 1961 "Wrong expression for enumeration field class label: "
08da4f77 1962 "node-type=%d, label=\"%s\"", iter->type,
e98a2d6e
PP
1963 label);
1964 ret = -EINVAL;
1965 goto error;
1966 }
1967
1968 if (nr_vals == 0) {
1969 target = &start;
1970 } else {
1971 target = &end;
1972 }
1973
1974 switch (iter->u.unary_expression.type) {
1975 case UNARY_SIGNED_CONSTANT:
44c440bc
PP
1976 target->is_signed = true;
1977 target->value.i =
1978 iter->u.unary_expression.u.signed_constant;
e98a2d6e
PP
1979 break;
1980 case UNARY_UNSIGNED_CONSTANT:
44c440bc
PP
1981 target->is_signed = false;
1982 target->value.u =
e98a2d6e
PP
1983 iter->u.unary_expression.u.unsigned_constant;
1984 break;
1985 default:
50f6fce8 1986 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
5cd6d0e5 1987 "Invalid enumeration field class entry: "
08da4f77
PP
1988 "expecting constant signed or unsigned integer: "
1989 "node-type=%d, label=\"%s\"",
1990 iter->u.unary_expression.type, label);
e98a2d6e
PP
1991 ret = -EINVAL;
1992 goto error;
1993 }
1994
1995 if (nr_vals > 1) {
50f6fce8 1996 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
5cd6d0e5 1997 "Invalid enumeration field class entry: label=\"%s\"",
e98a2d6e
PP
1998 label);
1999 ret = -EINVAL;
2000 goto error;
2001 }
2002
2003 nr_vals++;
2004 }
2005
2006 if (nr_vals == 0) {
2007 start = *last;
2008 }
2009
2010 if (nr_vals <= 1) {
2011 end = start;
2012 }
2013
44c440bc
PP
2014 if (end.is_signed) {
2015 last->value.i = end.value.i + 1;
2016 } else {
2017 last->value.u = end.value.u + 1;
2018 }
e98a2d6e 2019
45c51519 2020 ctf_field_class_enum_map_range(enum_decl, label,
44c440bc 2021 start.value.u, end.value.u);
e98a2d6e
PP
2022 return 0;
2023
2024error:
2025 return ret;
2026}
2027
2028static
cf81cdae 2029int visit_enum_decl(struct ctf_visitor_generate_ir *ctx, const char *name,
5cd6d0e5 2030 struct ctf_node *container_cls,
44c440bc 2031 struct bt_list_head *enumerator_list,
5cd6d0e5 2032 int has_body, struct ctf_field_class_enum **enum_decl)
e98a2d6e
PP
2033{
2034 int ret = 0;
2035 GQuark qdummy_id;
5cd6d0e5 2036 struct ctf_field_class_int *integer_decl = NULL;
e98a2d6e 2037
44c440bc 2038 BT_ASSERT(enum_decl);
e98a2d6e
PP
2039 *enum_decl = NULL;
2040
2041 /* For named enum (without body), lookup in declaration scope */
2042 if (!has_body) {
e98a2d6e 2043 if (!name) {
50f6fce8 2044 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless enumeration field class: missing name.");
e98a2d6e
PP
2045 ret = -EPERM;
2046 goto error;
2047 }
2048
0746848c 2049 *enum_decl = ctx_decl_scope_lookup_enum(ctx, ctx->current_scope,
44c440bc 2050 name, -1, true);
e98a2d6e 2051 if (!*enum_decl) {
50f6fce8 2052 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: "
08da4f77 2053 "name=\"enum %s\"", name);
e98a2d6e
PP
2054 ret = -EINVAL;
2055 goto error;
2056 }
e98a2d6e
PP
2057 } else {
2058 struct ctf_node *iter;
44c440bc
PP
2059 struct uori last_value = {
2060 .is_signed = false,
087cd0f5
SM
2061 .value = {
2062 .u = 0,
2063 },
44c440bc 2064 };
e98a2d6e
PP
2065
2066 if (name) {
0746848c 2067 if (ctx_decl_scope_lookup_enum(ctx, ctx->current_scope,
44c440bc 2068 name, 1, false)) {
50f6fce8 2069 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Enumeration field class already declared in local scope: "
08da4f77 2070 "name=\"enum %s\"", name);
e98a2d6e
PP
2071 ret = -EINVAL;
2072 goto error;
2073 }
2074 }
2075
5cd6d0e5 2076 if (!container_cls) {
087cd0f5
SM
2077 integer_decl = ctf_field_class_as_int(ctx_decl_scope_lookup_alias(ctx,
2078 ctx->current_scope, "int", -1, true));
e98a2d6e 2079 if (!integer_decl) {
50f6fce8 2080 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find implicit `int` field class alias for enumeration field class.");
e98a2d6e
PP
2081 ret = -EINVAL;
2082 goto error;
2083 }
2084 } else {
087cd0f5
SM
2085 ctf_field_class *decl;
2086
5cd6d0e5 2087 ret = visit_field_class_declarator(ctx, container_cls,
087cd0f5 2088 &qdummy_id, NULL, &decl, NULL);
e98a2d6e 2089 if (ret) {
087cd0f5 2090 BT_ASSERT(!decl);
e98a2d6e
PP
2091 ret = -EINVAL;
2092 goto error;
2093 }
087cd0f5
SM
2094
2095 integer_decl = ctf_field_class_as_int(decl);
e98a2d6e
PP
2096 }
2097
f6ccaed9 2098 BT_ASSERT(integer_decl);
e98a2d6e 2099
864cad70 2100 if (integer_decl->base.base.type != CTF_FIELD_CLASS_TYPE_INT) {
50f6fce8 2101 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Container field class for enumeration field class is not an integer field class: "
864cad70 2102 "fc-type=%d", integer_decl->base.base.type);
e98a2d6e
PP
2103 ret = -EINVAL;
2104 goto error;
2105 }
2106
5cd6d0e5 2107 *enum_decl = ctf_field_class_enum_create();
44c440bc
PP
2108 BT_ASSERT(*enum_decl);
2109 (*enum_decl)->base.base.base.alignment =
2110 integer_decl->base.base.alignment;
087cd0f5
SM
2111 ctf_field_class_int_copy_content(
2112 &(*enum_decl)->base, integer_decl);
44c440bc 2113 last_value.is_signed = (*enum_decl)->base.is_signed;
e98a2d6e
PP
2114
2115 bt_list_for_each_entry(iter, enumerator_list, siblings) {
2116 ret = visit_enum_decl_entry(ctx, iter, *enum_decl,
44c440bc 2117 &last_value);
e98a2d6e 2118 if (ret) {
50f6fce8 2119 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
5cd6d0e5 2120 "Cannot visit enumeration field class entry: "
28973adf 2121 "ret=%d", ret);
e98a2d6e
PP
2122 goto error;
2123 }
2124 }
2125
2126 if (name) {
0746848c
PP
2127 ret = ctx_decl_scope_register_enum(ctx,
2128 ctx->current_scope, name, *enum_decl);
e98a2d6e 2129 if (ret) {
50f6fce8 2130 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register enumeration field class in declaration scope: "
28973adf 2131 "ret=%d", ret);
e98a2d6e
PP
2132 goto error;
2133 }
2134 }
2135 }
2136
44c440bc 2137 goto end;
e98a2d6e
PP
2138
2139error:
087cd0f5 2140 ctf_field_class_destroy(&(*enum_decl)->base.base.base);
44c440bc 2141 *enum_decl = NULL;
e98a2d6e 2142
44c440bc 2143end:
087cd0f5 2144 ctf_field_class_destroy(&integer_decl->base.base);
44c440bc 2145 integer_decl = NULL;
e98a2d6e
PP
2146 return ret;
2147}
2148
2149static
cf81cdae 2150int visit_field_class_specifier(struct ctf_visitor_generate_ir *ctx,
5cd6d0e5
PP
2151 struct ctf_node *cls_specifier_list,
2152 struct ctf_field_class **decl)
e98a2d6e
PP
2153{
2154 int ret = 0;
2155 GString *str = NULL;
e98a2d6e
PP
2156
2157 *decl = NULL;
2158 str = g_string_new("");
5cd6d0e5 2159 ret = get_class_specifier_list_name(ctx, cls_specifier_list, str);
e98a2d6e 2160 if (ret) {
50f6fce8 2161 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
5cd6d0e5 2162 "Cannot get field class specifier list's name: ret=%d", ret);
e98a2d6e
PP
2163 goto error;
2164 }
2165
0746848c
PP
2166 *decl = ctx_decl_scope_lookup_alias(ctx, ctx->current_scope, str->str,
2167 -1, true);
e98a2d6e 2168 if (!*decl) {
50f6fce8 2169 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
5cd6d0e5 2170 "Cannot find field class alias: name=\"%s\"", str->str);
e98a2d6e
PP
2171 ret = -EINVAL;
2172 goto error;
2173 }
2174
44c440bc 2175 goto end;
e98a2d6e
PP
2176
2177error:
5cd6d0e5 2178 ctf_field_class_destroy(*decl);
44c440bc
PP
2179 *decl = NULL;
2180
2181end:
e98a2d6e 2182 if (str) {
44c440bc 2183 g_string_free(str, TRUE);
e98a2d6e
PP
2184 }
2185
e98a2d6e
PP
2186 return ret;
2187}
2188
2189static
cf81cdae 2190int visit_integer_decl(struct ctf_visitor_generate_ir *ctx,
44c440bc 2191 struct bt_list_head *expressions,
5cd6d0e5 2192 struct ctf_field_class_int **integer_decl)
e98a2d6e
PP
2193{
2194 int set = 0;
2195 int ret = 0;
44c440bc 2196 int signedness = 0;
e98a2d6e
PP
2197 struct ctf_node *expression;
2198 uint64_t alignment = 0, size = 0;
0f2d58c9 2199 struct ctf_clock_class *mapped_clock_class = NULL;
44c440bc 2200 enum ctf_encoding encoding = CTF_ENCODING_NONE;
4cdfc5e8 2201 bt_field_class_integer_preferred_display_base base =
5cd6d0e5 2202 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
44c440bc 2203 enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
e98a2d6e
PP
2204
2205 *integer_decl = NULL;
2206
2207 bt_list_for_each_entry(expression, expressions, siblings) {
2208 struct ctf_node *left, *right;
2209
2210 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left,
2211 struct ctf_node, siblings);
2212 right = _BT_LIST_FIRST_ENTRY(
2213 &expression->u.ctf_expression.right, struct ctf_node,
2214 siblings);
2215
2216 if (left->u.unary_expression.type != UNARY_STRING) {
50f6fce8 2217 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left,
28973adf
PP
2218 "Unexpected unary expression type: type=%d",
2219 left->u.unary_expression.type);
e98a2d6e
PP
2220 ret = -EINVAL;
2221 goto error;
2222 }
2223
2242b43d 2224 if (strcmp(left->u.unary_expression.u.string, "signed") == 0) {
e98a2d6e 2225 if (_IS_SET(&set, _INTEGER_SIGNED_SET)) {
50f6fce8 2226 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "signed",
5cd6d0e5 2227 "integer field class");
e98a2d6e
PP
2228 ret = -EPERM;
2229 goto error;
2230 }
2231
0746848c 2232 signedness = get_boolean(ctx, right);
e98a2d6e 2233 if (signedness < 0) {
50f6fce8 2234 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2235 "Invalid boolean value for integer field class's `signed` attribute: "
28973adf 2236 "ret=%d", ret);
e98a2d6e
PP
2237 ret = -EINVAL;
2238 goto error;
2239 }
2240
2241 _SET(&set, _INTEGER_SIGNED_SET);
2242b43d 2242 } else if (strcmp(left->u.unary_expression.u.string, "byte_order") == 0) {
e98a2d6e 2243 if (_IS_SET(&set, _INTEGER_BYTE_ORDER_SET)) {
50f6fce8 2244 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "byte_order",
5cd6d0e5 2245 "integer field class");
e98a2d6e
PP
2246 ret = -EPERM;
2247 goto error;
2248 }
2249
2250 byte_order = get_real_byte_order(ctx, right);
e2bd7d40 2251 if (byte_order == CTF_BYTE_ORDER_UNKNOWN) {
50f6fce8 2252 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2253 "Invalid `byte_order` attribute in integer field class: "
08da4f77 2254 "ret=%d", ret);
e98a2d6e
PP
2255 ret = -EINVAL;
2256 goto error;
2257 }
2258
2259 _SET(&set, _INTEGER_BYTE_ORDER_SET);
2242b43d 2260 } else if (strcmp(left->u.unary_expression.u.string, "size") == 0) {
e98a2d6e 2261 if (_IS_SET(&set, _INTEGER_SIZE_SET)) {
50f6fce8 2262 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "size",
5cd6d0e5 2263 "integer field class");
e98a2d6e
PP
2264 ret = -EPERM;
2265 goto error;
2266 }
2267
2268 if (right->u.unary_expression.type !=
2269 UNARY_UNSIGNED_CONSTANT) {
50f6fce8 2270 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2271 "Invalid `size` attribute in integer field class: "
08da4f77
PP
2272 "expecting unsigned constant integer: "
2273 "node-type=%d",
2274 right->u.unary_expression.type);
e98a2d6e
PP
2275 ret = -EINVAL;
2276 goto error;
2277 }
2278
2279 size = right->u.unary_expression.u.unsigned_constant;
2280 if (size == 0) {
50f6fce8 2281 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2282 "Invalid `size` attribute in integer field class: "
08da4f77
PP
2283 "expecting positive constant integer: "
2284 "size=%" PRIu64, size);
e98a2d6e
PP
2285 ret = -EINVAL;
2286 goto error;
2287 } else if (size > 64) {
50f6fce8 2288 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2289 "Invalid `size` attribute in integer field class: "
08da4f77
PP
2290 "integer fields over 64 bits are not supported as of this version: "
2291 "size=%" PRIu64, size);
e98a2d6e
PP
2292 ret = -EINVAL;
2293 goto error;
2294 }
2295
2296 _SET(&set, _INTEGER_SIZE_SET);
2242b43d 2297 } else if (strcmp(left->u.unary_expression.u.string, "align") == 0) {
e98a2d6e 2298 if (_IS_SET(&set, _INTEGER_ALIGN_SET)) {
50f6fce8 2299 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "align",
5cd6d0e5 2300 "integer field class");
e98a2d6e
PP
2301 ret = -EPERM;
2302 goto error;
2303 }
2304
2305 if (right->u.unary_expression.type !=
2306 UNARY_UNSIGNED_CONSTANT) {
50f6fce8 2307 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2308 "Invalid `align` attribute in integer field class: "
08da4f77
PP
2309 "expecting unsigned constant integer: "
2310 "node-type=%d",
2311 right->u.unary_expression.type);
e98a2d6e
PP
2312 ret = -EINVAL;
2313 goto error;
2314 }
2315
2316 alignment =
2317 right->u.unary_expression.u.unsigned_constant;
2318 if (!is_align_valid(alignment)) {
50f6fce8 2319 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2320 "Invalid `align` attribute in integer field class: "
08da4f77
PP
2321 "expecting power of two: "
2322 "align=%" PRIu64, alignment);
e98a2d6e
PP
2323 ret = -EINVAL;
2324 goto error;
2325 }
2326
2327 _SET(&set, _INTEGER_ALIGN_SET);
2242b43d 2328 } else if (strcmp(left->u.unary_expression.u.string, "base") == 0) {
e98a2d6e 2329 if (_IS_SET(&set, _INTEGER_BASE_SET)) {
50f6fce8 2330 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "base",
5cd6d0e5 2331 "integer field class");
e98a2d6e
PP
2332 ret = -EPERM;
2333 goto error;
2334 }
2335
2336 switch (right->u.unary_expression.type) {
2337 case UNARY_UNSIGNED_CONSTANT:
2338 {
2339 uint64_t constant = right->u.unary_expression.
2340 u.unsigned_constant;
2341
2342 switch (constant) {
2343 case 2:
5cd6d0e5 2344 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY;
e98a2d6e
PP
2345 break;
2346 case 8:
5cd6d0e5 2347 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL;
e98a2d6e
PP
2348 break;
2349 case 10:
5cd6d0e5 2350 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
e98a2d6e
PP
2351 break;
2352 case 16:
5cd6d0e5 2353 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
e98a2d6e
PP
2354 break;
2355 default:
50f6fce8 2356 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2357 "Invalid `base` attribute in integer field class: "
08da4f77 2358 "base=%" PRIu64,
e98a2d6e
PP
2359 right->u.unary_expression.u.unsigned_constant);
2360 ret = -EINVAL;
2361 goto error;
2362 }
2363 break;
2364 }
2365 case UNARY_STRING:
2366 {
1a6da3f9 2367 char *s_right = ctf_ast_concatenate_unary_strings(
e98a2d6e
PP
2368 &expression->u.ctf_expression.right);
2369 if (!s_right) {
50f6fce8 2370 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2371 "Unexpected unary expression for integer field class's `base` attribute.");
e98a2d6e
PP
2372 ret = -EINVAL;
2373 goto error;
2374 }
2375
2242b43d
PP
2376 if (strcmp(s_right, "decimal") == 0 ||
2377 strcmp(s_right, "dec") == 0 ||
2378 strcmp(s_right, "d") == 0 ||
2379 strcmp(s_right, "i") == 0 ||
2380 strcmp(s_right, "u") == 0) {
5cd6d0e5 2381 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
2242b43d
PP
2382 } else if (strcmp(s_right, "hexadecimal") == 0 ||
2383 strcmp(s_right, "hex") == 0 ||
2384 strcmp(s_right, "x") == 0 ||
2385 strcmp(s_right, "X") == 0 ||
2386 strcmp(s_right, "p") == 0) {
5cd6d0e5 2387 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
2242b43d
PP
2388 } else if (strcmp(s_right, "octal") == 0 ||
2389 strcmp(s_right, "oct") == 0 ||
2390 strcmp(s_right, "o") == 0) {
5cd6d0e5 2391 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL;
2242b43d
PP
2392 } else if (strcmp(s_right, "binary") == 0 ||
2393 strcmp(s_right, "b") == 0) {
5cd6d0e5 2394 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY;
e98a2d6e 2395 } else {
50f6fce8 2396 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2397 "Unexpected unary expression for integer field class's `base` attribute: "
08da4f77 2398 "base=\"%s\"", s_right);
e98a2d6e
PP
2399 g_free(s_right);
2400 ret = -EINVAL;
2401 goto error;
2402 }
2403
2404 g_free(s_right);
2405 break;
2406 }
2407 default:
50f6fce8 2408 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2409 "Invalid `base` attribute in integer field class: "
08da4f77 2410 "expecting unsigned constant integer or unary string.");
e98a2d6e
PP
2411 ret = -EINVAL;
2412 goto error;
2413 }
2414
2415 _SET(&set, _INTEGER_BASE_SET);
2242b43d 2416 } else if (strcmp(left->u.unary_expression.u.string, "encoding") == 0) {
e98a2d6e
PP
2417 char *s_right;
2418
2419 if (_IS_SET(&set, _INTEGER_ENCODING_SET)) {
50f6fce8 2420 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "encoding",
5cd6d0e5 2421 "integer field class");
e98a2d6e
PP
2422 ret = -EPERM;
2423 goto error;
2424 }
2425
2426 if (right->u.unary_expression.type != UNARY_STRING) {
50f6fce8 2427 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2428 "Invalid `encoding` attribute in integer field class: "
08da4f77 2429 "expecting unary string.");
e98a2d6e
PP
2430 ret = -EINVAL;
2431 goto error;
2432 }
2433
1a6da3f9 2434 s_right = ctf_ast_concatenate_unary_strings(
e98a2d6e
PP
2435 &expression->u.ctf_expression.right);
2436 if (!s_right) {
50f6fce8 2437 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2438 "Unexpected unary expression for integer field class's `encoding` attribute.");
e98a2d6e
PP
2439 ret = -EINVAL;
2440 goto error;
2441 }
2442
2242b43d
PP
2443 if (strcmp(s_right, "UTF8") == 0 ||
2444 strcmp(s_right, "utf8") == 0 ||
2445 strcmp(s_right, "utf-8") == 0 ||
2446 strcmp(s_right, "UTF-8") == 0 ||
2447 strcmp(s_right, "ASCII") == 0 ||
2448 strcmp(s_right, "ascii") == 0) {
44c440bc 2449 encoding = CTF_ENCODING_UTF8;
2242b43d 2450 } else if (strcmp(s_right, "none") == 0) {
44c440bc 2451 encoding = CTF_ENCODING_NONE;
e98a2d6e 2452 } else {
50f6fce8 2453 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2454 "Invalid `encoding` attribute in integer field class: "
08da4f77 2455 "unknown encoding: encoding=\"%s\"",
e98a2d6e
PP
2456 s_right);
2457 g_free(s_right);
2458 ret = -EINVAL;
2459 goto error;
2460 }
2461
2462 g_free(s_right);
2463 _SET(&set, _INTEGER_ENCODING_SET);
2242b43d 2464 } else if (strcmp(left->u.unary_expression.u.string, "map") == 0) {
e98a2d6e
PP
2465 const char *clock_name;
2466
2467 if (_IS_SET(&set, _INTEGER_MAP_SET)) {
50f6fce8 2468 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "map",
5cd6d0e5 2469 "integer field class");
e98a2d6e
PP
2470 ret = -EPERM;
2471 goto error;
2472 }
2473
2474 if (right->u.unary_expression.type != UNARY_STRING) {
50f6fce8 2475 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2476 "Invalid `map` attribute in integer field class: "
08da4f77 2477 "expecting unary string.");
e98a2d6e
PP
2478 ret = -EINVAL;
2479 goto error;
2480 }
2481
2482 clock_name =
2483 get_map_clock_name_value(
2484 &expression->u.ctf_expression.right);
2485 if (!clock_name) {
1a6da3f9 2486 char *s_right = ctf_ast_concatenate_unary_strings(
e98a2d6e
PP
2487 &expression->u.ctf_expression.right);
2488
2489 if (!s_right) {
50f6fce8 2490 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2491 "Unexpected unary expression for integer field class's `map` attribute.");
e98a2d6e
PP
2492 ret = -EINVAL;
2493 goto error;
2494 }
2495
f7b785ac 2496 _BT_COMP_LOGE_NODE(right,
5cd6d0e5 2497 "Invalid `map` attribute in integer field class: "
08da4f77 2498 "cannot find clock class at this point: name=\"%s\"",
e98a2d6e
PP
2499 s_right);
2500 _SET(&set, _INTEGER_MAP_SET);
2501 g_free(s_right);
2502 continue;
2503 }
2504
44c440bc
PP
2505 mapped_clock_class =
2506 ctf_trace_class_borrow_clock_class_by_name(
2507 ctx->ctf_tc, clock_name);
2508 if (!mapped_clock_class) {
50f6fce8 2509 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2510 "Invalid `map` attribute in integer field class: "
08da4f77 2511 "cannot find clock class at this point: name=\"%s\"",
e98a2d6e
PP
2512 clock_name);
2513 ret = -EINVAL;
2514 goto error;
2515 }
2516
2517 _SET(&set, _INTEGER_MAP_SET);
2518 } else {
f7b785ac 2519 _BT_COMP_LOGW_NODE(left,
5cd6d0e5 2520 "Unknown attribute in integer field class: "
08da4f77 2521 "attr-name=\"%s\"",
e98a2d6e
PP
2522 left->u.unary_expression.u.string);
2523 }
2524 }
2525
2526 if (!_IS_SET(&set, _INTEGER_SIZE_SET)) {
50f6fce8 2527 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `size` attribute in integer field class.");
e98a2d6e
PP
2528 ret = -EPERM;
2529 goto error;
2530 }
2531
2532 if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2533 if (size % CHAR_BIT) {
2534 /* Bit-packed alignment */
2535 alignment = 1;
2536 } else {
2537 /* Byte-packed alignment */
2538 alignment = CHAR_BIT;
2539 }
2540 }
2541
5cd6d0e5 2542 *integer_decl = ctf_field_class_int_create();
44c440bc
PP
2543 BT_ASSERT(*integer_decl);
2544 (*integer_decl)->base.base.alignment = alignment;
2545 (*integer_decl)->base.byte_order = byte_order;
2546 (*integer_decl)->base.size = size;
2547 (*integer_decl)->is_signed = (signedness > 0);
2548 (*integer_decl)->disp_base = base;
2549 (*integer_decl)->encoding = encoding;
398454ed 2550 (*integer_decl)->mapped_clock_class = mapped_clock_class;
e98a2d6e
PP
2551 return 0;
2552
2553error:
087cd0f5 2554 ctf_field_class_destroy(&(*integer_decl)->base.base);
44c440bc 2555 *integer_decl = NULL;
e98a2d6e
PP
2556 return ret;
2557}
2558
2559static
cf81cdae 2560int visit_floating_point_number_decl(struct ctf_visitor_generate_ir *ctx,
44c440bc 2561 struct bt_list_head *expressions,
5cd6d0e5 2562 struct ctf_field_class_float **float_decl)
e98a2d6e
PP
2563{
2564 int set = 0;
2565 int ret = 0;
2566 struct ctf_node *expression;
2567 uint64_t alignment = 1, exp_dig = 0, mant_dig = 0;
44c440bc 2568 enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
e98a2d6e
PP
2569
2570 *float_decl = NULL;
2571
2572 bt_list_for_each_entry(expression, expressions, siblings) {
2573 struct ctf_node *left, *right;
2574
2575 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left,
2576 struct ctf_node, siblings);
2577 right = _BT_LIST_FIRST_ENTRY(
2578 &expression->u.ctf_expression.right, struct ctf_node,
2579 siblings);
2580
2581 if (left->u.unary_expression.type != UNARY_STRING) {
50f6fce8 2582 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left,
28973adf
PP
2583 "Unexpected unary expression type: type=%d",
2584 left->u.unary_expression.type);
e98a2d6e
PP
2585 ret = -EINVAL;
2586 goto error;
2587 }
2588
2242b43d 2589 if (strcmp(left->u.unary_expression.u.string, "byte_order") == 0) {
e98a2d6e 2590 if (_IS_SET(&set, _FLOAT_BYTE_ORDER_SET)) {
50f6fce8 2591 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "byte_order",
5cd6d0e5 2592 "floating point number field class");
e98a2d6e
PP
2593 ret = -EPERM;
2594 goto error;
2595 }
2596
2597 byte_order = get_real_byte_order(ctx, right);
e2bd7d40 2598 if (byte_order == CTF_BYTE_ORDER_UNKNOWN) {
50f6fce8 2599 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2600 "Invalid `byte_order` attribute in floating point number field class: "
08da4f77 2601 "ret=%d", ret);
e98a2d6e
PP
2602 ret = -EINVAL;
2603 goto error;
2604 }
2605
2606 _SET(&set, _FLOAT_BYTE_ORDER_SET);
2242b43d 2607 } else if (strcmp(left->u.unary_expression.u.string, "exp_dig") == 0) {
e98a2d6e 2608 if (_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
50f6fce8 2609 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "exp_dig",
5cd6d0e5 2610 "floating point number field class");
e98a2d6e
PP
2611 ret = -EPERM;
2612 goto error;
2613 }
2614
2615 if (right->u.unary_expression.type !=
2616 UNARY_UNSIGNED_CONSTANT) {
50f6fce8 2617 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2618 "Invalid `exp_dig` attribute in floating point number field class: "
08da4f77
PP
2619 "expecting unsigned constant integer: "
2620 "node-type=%d",
2621 right->u.unary_expression.type);
e98a2d6e
PP
2622 ret = -EINVAL;
2623 goto error;
2624 }
2625
2626 exp_dig = right->u.unary_expression.u.unsigned_constant;
2627 _SET(&set, _FLOAT_EXP_DIG_SET);
2242b43d 2628 } else if (strcmp(left->u.unary_expression.u.string, "mant_dig") == 0) {
e98a2d6e 2629 if (_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
50f6fce8 2630 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "mant_dig",
5cd6d0e5 2631 "floating point number field class");
e98a2d6e
PP
2632 ret = -EPERM;
2633 goto error;
2634 }
2635
2636 if (right->u.unary_expression.type !=
2637 UNARY_UNSIGNED_CONSTANT) {
50f6fce8 2638 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2639 "Invalid `mant_dig` attribute in floating point number field class: "
08da4f77
PP
2640 "expecting unsigned constant integer: "
2641 "node-type=%d",
2642 right->u.unary_expression.type);
e98a2d6e
PP
2643 ret = -EINVAL;
2644 goto error;
2645 }
2646
2647 mant_dig = right->u.unary_expression.u.
2648 unsigned_constant;
2649 _SET(&set, _FLOAT_MANT_DIG_SET);
2242b43d 2650 } else if (strcmp(left->u.unary_expression.u.string, "align") == 0) {
e98a2d6e 2651 if (_IS_SET(&set, _FLOAT_ALIGN_SET)) {
50f6fce8 2652 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "align",
5cd6d0e5 2653 "floating point number field class");
e98a2d6e
PP
2654 ret = -EPERM;
2655 goto error;
2656 }
2657
2658 if (right->u.unary_expression.type !=
2659 UNARY_UNSIGNED_CONSTANT) {
50f6fce8 2660 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2661 "Invalid `align` attribute in floating point number field class: "
08da4f77
PP
2662 "expecting unsigned constant integer: "
2663 "node-type=%d",
2664 right->u.unary_expression.type);
e98a2d6e
PP
2665 ret = -EINVAL;
2666 goto error;
2667 }
2668
2669 alignment = right->u.unary_expression.u.
2670 unsigned_constant;
2671
2672 if (!is_align_valid(alignment)) {
50f6fce8 2673 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2674 "Invalid `align` attribute in floating point number field class: "
08da4f77
PP
2675 "expecting power of two: "
2676 "align=%" PRIu64, alignment);
e98a2d6e
PP
2677 ret = -EINVAL;
2678 goto error;
2679 }
2680
2681 _SET(&set, _FLOAT_ALIGN_SET);
2682 } else {
f7b785ac 2683 _BT_COMP_LOGW_NODE(left,
5cd6d0e5 2684 "Unknown attribute in floating point number field class: "
08da4f77 2685 "attr-name=\"%s\"",
e98a2d6e
PP
2686 left->u.unary_expression.u.string);
2687 }
2688 }
2689
2690 if (!_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
50f6fce8 2691 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `mant_dig` attribute in floating point number field class.");
e98a2d6e
PP
2692 ret = -EPERM;
2693 goto error;
2694 }
2695
2696 if (!_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
50f6fce8 2697 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `exp_dig` attribute in floating point number field class.");
e98a2d6e
PP
2698 ret = -EPERM;
2699 goto error;
2700 }
2701
44c440bc 2702 if (mant_dig != 24 && mant_dig != 53) {
50f6fce8 2703 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53.");
44c440bc
PP
2704 ret = -EPERM;
2705 goto error;
2706 }
2707
2708 if (mant_dig == 24 && exp_dig != 8) {
50f6fce8 2709 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
44c440bc
PP
2710 ret = -EPERM;
2711 goto error;
2712 }
2713
2714 if (mant_dig == 53 && exp_dig != 11) {
50f6fce8 2715 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
44c440bc
PP
2716 ret = -EPERM;
2717 goto error;
2718 }
2719
e98a2d6e
PP
2720 if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2721 if ((mant_dig + exp_dig) % CHAR_BIT) {
2722 /* Bit-packed alignment */
2723 alignment = 1;
2724 } else {
2725 /* Byte-packed alignment */
2726 alignment = CHAR_BIT;
2727 }
2728 }
2729
5cd6d0e5 2730 *float_decl = ctf_field_class_float_create();
44c440bc
PP
2731 BT_ASSERT(*float_decl);
2732 (*float_decl)->base.base.alignment = alignment;
2733 (*float_decl)->base.byte_order = byte_order;
2734 (*float_decl)->base.size = mant_dig + exp_dig;
e98a2d6e
PP
2735 return 0;
2736
2737error:
087cd0f5 2738 ctf_field_class_destroy(&(*float_decl)->base.base);
44c440bc 2739 *float_decl = NULL;
e98a2d6e
PP
2740 return ret;
2741}
2742
2743static
cf81cdae 2744int visit_string_decl(struct ctf_visitor_generate_ir *ctx,
44c440bc 2745 struct bt_list_head *expressions,
5cd6d0e5 2746 struct ctf_field_class_string **string_decl)
e98a2d6e
PP
2747{
2748 int set = 0;
2749 int ret = 0;
2750 struct ctf_node *expression;
44c440bc 2751 enum ctf_encoding encoding = CTF_ENCODING_UTF8;
e98a2d6e
PP
2752
2753 *string_decl = NULL;
2754
2755 bt_list_for_each_entry(expression, expressions, siblings) {
2756 struct ctf_node *left, *right;
2757
2758 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left,
2759 struct ctf_node, siblings);
2760 right = _BT_LIST_FIRST_ENTRY(
2761 &expression->u.ctf_expression.right, struct ctf_node,
2762 siblings);
2763
2764 if (left->u.unary_expression.type != UNARY_STRING) {
50f6fce8 2765 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left,
28973adf
PP
2766 "Unexpected unary expression type: type=%d",
2767 left->u.unary_expression.type);
e98a2d6e
PP
2768 ret = -EINVAL;
2769 goto error;
2770 }
2771
2242b43d 2772 if (strcmp(left->u.unary_expression.u.string, "encoding") == 0) {
e98a2d6e
PP
2773 char *s_right;
2774
2775 if (_IS_SET(&set, _STRING_ENCODING_SET)) {
50f6fce8 2776 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "encoding",
5cd6d0e5 2777 "string field class");
e98a2d6e
PP
2778 ret = -EPERM;
2779 goto error;
2780 }
2781
2782 if (right->u.unary_expression.type != UNARY_STRING) {
50f6fce8 2783 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2784 "Invalid `encoding` attribute in string field class: "
08da4f77 2785 "expecting unary string.");
e98a2d6e
PP
2786 ret = -EINVAL;
2787 goto error;
2788 }
2789
1a6da3f9 2790 s_right = ctf_ast_concatenate_unary_strings(
e98a2d6e
PP
2791 &expression->u.ctf_expression.right);
2792 if (!s_right) {
50f6fce8 2793 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2794 "Unexpected unary expression for string field class's `encoding` attribute.");
e98a2d6e
PP
2795 ret = -EINVAL;
2796 goto error;
2797 }
2798
2242b43d
PP
2799 if (strcmp(s_right, "UTF8") == 0 ||
2800 strcmp(s_right, "utf8") == 0 ||
2801 strcmp(s_right, "utf-8") == 0 ||
2802 strcmp(s_right, "UTF-8") == 0 ||
2803 strcmp(s_right, "ASCII") == 0 ||
2804 strcmp(s_right, "ascii") == 0) {
44c440bc 2805 encoding = CTF_ENCODING_UTF8;
2242b43d 2806 } else if (strcmp(s_right, "none") == 0) {
44c440bc 2807 encoding = CTF_ENCODING_NONE;
e98a2d6e 2808 } else {
50f6fce8 2809 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
5cd6d0e5 2810 "Invalid `encoding` attribute in string field class: "
08da4f77 2811 "unknown encoding: encoding=\"%s\"",
e98a2d6e
PP
2812 s_right);
2813 g_free(s_right);
2814 ret = -EINVAL;
2815 goto error;
2816 }
2817
2818 g_free(s_right);
2819 _SET(&set, _STRING_ENCODING_SET);
2820 } else {
f7b785ac 2821 _BT_COMP_LOGW_NODE(left,
5cd6d0e5 2822 "Unknown attribute in string field class: "
08da4f77 2823 "attr-name=\"%s\"",
e98a2d6e
PP
2824 left->u.unary_expression.u.string);
2825 }
2826 }
2827
5cd6d0e5 2828 *string_decl = ctf_field_class_string_create();
44c440bc
PP
2829 BT_ASSERT(*string_decl);
2830 (*string_decl)->encoding = encoding;
e98a2d6e
PP
2831 return 0;
2832
2833error:
087cd0f5 2834 ctf_field_class_destroy(&(*string_decl)->base);
44c440bc 2835 *string_decl = NULL;
e98a2d6e
PP
2836 return ret;
2837}
2838
2839static
cf81cdae 2840int visit_field_class_specifier_list(struct ctf_visitor_generate_ir *ctx,
5cd6d0e5 2841 struct ctf_node *ts_list, struct ctf_field_class **decl)
e98a2d6e
PP
2842{
2843 int ret = 0;
2844 struct ctf_node *first, *node;
2845
2846 *decl = NULL;
2847
2848 if (ts_list->type != NODE_TYPE_SPECIFIER_LIST) {
50f6fce8 2849 _BT_COMP_LOGE_APPEND_CAUSE_NODE(ts_list,
28973adf 2850 "Unexpected node type: node-type=%d", ts_list->type);
e98a2d6e
PP
2851 ret = -EINVAL;
2852 goto error;
2853 }
2854
5cd6d0e5 2855 first = _BT_LIST_FIRST_ENTRY(&ts_list->u.field_class_specifier_list.head,
e98a2d6e
PP
2856 struct ctf_node, siblings);
2857 if (first->type != NODE_TYPE_SPECIFIER) {
50f6fce8 2858 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first,
28973adf 2859 "Unexpected node type: node-type=%d", first->type);
e98a2d6e
PP
2860 ret = -EINVAL;
2861 goto error;
2862 }
2863
5cd6d0e5 2864 node = first->u.field_class_specifier.node;
e98a2d6e 2865
5cd6d0e5 2866 switch (first->u.field_class_specifier.type) {
087cd0f5
SM
2867 case TYPESPEC_INTEGER: {
2868 ctf_field_class_int *int_decl;
2869
e98a2d6e 2870 ret = visit_integer_decl(ctx, &node->u.integer.expressions,
087cd0f5 2871 &int_decl);
e98a2d6e 2872 if (ret) {
087cd0f5 2873 BT_ASSERT(!int_decl);
e98a2d6e
PP
2874 goto error;
2875 }
087cd0f5
SM
2876
2877 *decl = &int_decl->base.base;
e98a2d6e 2878 break;
087cd0f5
SM
2879 }
2880 case TYPESPEC_FLOATING_POINT: {
2881 ctf_field_class_float *float_decl;
2882
e98a2d6e 2883 ret = visit_floating_point_number_decl(ctx,
087cd0f5 2884 &node->u.floating_point.expressions, &float_decl);
e98a2d6e 2885 if (ret) {
087cd0f5 2886 BT_ASSERT(!float_decl);
e98a2d6e
PP
2887 goto error;
2888 }
087cd0f5
SM
2889
2890 *decl = &float_decl->base.base;
e98a2d6e 2891 break;
087cd0f5
SM
2892 }
2893 case TYPESPEC_STRING: {
2894 ctf_field_class_string *string_decl;
2895
e98a2d6e 2896 ret = visit_string_decl(ctx,
087cd0f5 2897 &node->u.string.expressions, &string_decl);
e98a2d6e 2898 if (ret) {
087cd0f5 2899 BT_ASSERT(!string_decl);
e98a2d6e
PP
2900 goto error;
2901 }
087cd0f5
SM
2902
2903 *decl = &string_decl->base;
e98a2d6e 2904 break;
087cd0f5
SM
2905 }
2906 case TYPESPEC_STRUCT: {
2907 ctf_field_class_struct *struct_decl;
2908
e98a2d6e
PP
2909 ret = visit_struct_decl(ctx, node->u._struct.name,
2910 &node->u._struct.declaration_list,
2911 node->u._struct.has_body,
087cd0f5 2912 &node->u._struct.min_align, &struct_decl);
e98a2d6e 2913 if (ret) {
087cd0f5 2914 BT_ASSERT(!struct_decl);
e98a2d6e
PP
2915 goto error;
2916 }
087cd0f5
SM
2917
2918 *decl = &struct_decl->base;
e98a2d6e 2919 break;
087cd0f5
SM
2920 }
2921 case TYPESPEC_VARIANT: {
2922 ctf_field_class_variant *variant_decl;
2923
e98a2d6e
PP
2924 ret = visit_variant_decl(ctx, node->u.variant.name,
2925 node->u.variant.choice,
2926 &node->u.variant.declaration_list,
087cd0f5 2927 node->u.variant.has_body, &variant_decl);
e98a2d6e 2928 if (ret) {
087cd0f5 2929 BT_ASSERT(!variant_decl);
e98a2d6e
PP
2930 goto error;
2931 }
087cd0f5
SM
2932
2933 *decl = &variant_decl->base;
e98a2d6e 2934 break;
087cd0f5
SM
2935 }
2936 case TYPESPEC_ENUM: {
2937 ctf_field_class_enum *enum_decl;
2938
e98a2d6e 2939 ret = visit_enum_decl(ctx, node->u._enum.enum_id,
5cd6d0e5 2940 node->u._enum.container_field_class,
e98a2d6e 2941 &node->u._enum.enumerator_list,
087cd0f5 2942 node->u._enum.has_body, &enum_decl);
e98a2d6e 2943 if (ret) {
087cd0f5 2944 BT_ASSERT(!enum_decl);
e98a2d6e
PP
2945 goto error;
2946 }
087cd0f5
SM
2947
2948 *decl = &enum_decl->base.base.base;
e98a2d6e 2949 break;
087cd0f5 2950 }
e98a2d6e
PP
2951 case TYPESPEC_VOID:
2952 case TYPESPEC_CHAR:
2953 case TYPESPEC_SHORT:
2954 case TYPESPEC_INT:
2955 case TYPESPEC_LONG:
2956 case TYPESPEC_FLOAT:
2957 case TYPESPEC_DOUBLE:
2958 case TYPESPEC_SIGNED:
2959 case TYPESPEC_UNSIGNED:
2960 case TYPESPEC_BOOL:
2961 case TYPESPEC_COMPLEX:
2962 case TYPESPEC_IMAGINARY:
2963 case TYPESPEC_CONST:
2964 case TYPESPEC_ID_TYPE:
5cd6d0e5 2965 ret = visit_field_class_specifier(ctx, ts_list, decl);
e98a2d6e 2966 if (ret) {
50f6fce8 2967 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first,
5cd6d0e5 2968 "Cannot visit field class specifier: ret=%d",
28973adf 2969 ret);
f6ccaed9 2970 BT_ASSERT(!*decl);
e98a2d6e
PP
2971 goto error;
2972 }
2973 break;
2974 default:
50f6fce8 2975 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first,
5cd6d0e5
PP
2976 "Unexpected field class specifier type: node-type=%d",
2977 first->u.field_class_specifier.type);
e98a2d6e
PP
2978 ret = -EINVAL;
2979 goto error;
2980 }
2981
f6ccaed9 2982 BT_ASSERT(*decl);
e98a2d6e
PP
2983 return 0;
2984
2985error:
087cd0f5 2986 ctf_field_class_destroy(*decl);
44c440bc 2987 *decl = NULL;
e98a2d6e
PP
2988 return ret;
2989}
2990
2991static
cf81cdae 2992int visit_event_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node,
44c440bc
PP
2993 struct ctf_event_class *event_class, uint64_t *stream_id,
2994 int *set)
e98a2d6e
PP
2995{
2996 int ret = 0;
2997 char *left = NULL;
e98a2d6e
PP
2998
2999 switch (node->type) {
3000 case NODE_TYPEDEF:
5cd6d0e5
PP
3001 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3002 &node->u.field_class_def.field_class_declarators);
e98a2d6e 3003 if (ret) {
50f6fce8 3004 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3005 "Cannot add field class found in event class.");
e98a2d6e
PP
3006 goto error;
3007 }
3008 break;
3009 case NODE_TYPEALIAS:
5cd6d0e5
PP
3010 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3011 node->u.field_class_alias.alias);
e98a2d6e 3012 if (ret) {
50f6fce8 3013 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3014 "Cannot add field class alias found in event class.");
e98a2d6e
PP
3015 goto error;
3016 }
3017 break;
3018 case NODE_CTF_EXPRESSION:
3019 {
1a6da3f9 3020 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
e98a2d6e 3021 if (!left) {
50f6fce8 3022 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
e98a2d6e
PP
3023 ret = -EINVAL;
3024 goto error;
3025 }
3026
2242b43d 3027 if (strcmp(left, "name") == 0) {
e98a2d6e
PP
3028 /* This is already known at this stage */
3029 if (_IS_SET(set, _EVENT_NAME_SET)) {
50f6fce8 3030 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "name", "event class");
e98a2d6e
PP
3031 ret = -EPERM;
3032 goto error;
3033 }
3034
3035 _SET(set, _EVENT_NAME_SET);
2242b43d 3036 } else if (strcmp(left, "id") == 0) {
bc85036f 3037 int64_t id = -1;
e98a2d6e
PP
3038
3039 if (_IS_SET(set, _EVENT_ID_SET)) {
50f6fce8 3040 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "id", "event class");
e98a2d6e
PP
3041 ret = -EPERM;
3042 goto error;
3043 }
3044
0746848c
PP
3045 ret = get_unary_unsigned(ctx,
3046 &node->u.ctf_expression.right,
e98a2d6e 3047 (uint64_t *) &id);
5eae0c3c
JG
3048 /* Only read "id" if get_unary_unsigned() succeeded. */
3049 if (ret || (!ret && id < 0)) {
50f6fce8 3050 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3051 "Unexpected unary expression for event class's `id` attribute.");
e98a2d6e
PP
3052 ret = -EINVAL;
3053 goto error;
3054 }
3055
44c440bc 3056 event_class->id = id;
e98a2d6e 3057 _SET(set, _EVENT_ID_SET);
2242b43d 3058 } else if (strcmp(left, "stream_id") == 0) {
e98a2d6e 3059 if (_IS_SET(set, _EVENT_STREAM_ID_SET)) {
50f6fce8 3060 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "stream_id",
08da4f77 3061 "event class");
e98a2d6e
PP
3062 ret = -EPERM;
3063 goto error;
3064 }
3065
0746848c
PP
3066 ret = get_unary_unsigned(ctx,
3067 &node->u.ctf_expression.right, stream_id);
44c440bc 3068
5eae0c3c
JG
3069 /*
3070 * Only read "stream_id" if get_unary_unsigned()
3071 * succeeded.
3072 */
1d9f5cd6 3073 if (ret) {
50f6fce8 3074 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3075 "Unexpected unary expression for event class's `stream_id` attribute.");
e98a2d6e
PP
3076 ret = -EINVAL;
3077 goto error;
3078 }
3079
3080 _SET(set, _EVENT_STREAM_ID_SET);
2242b43d 3081 } else if (strcmp(left, "context") == 0) {
e98a2d6e 3082 if (_IS_SET(set, _EVENT_CONTEXT_SET)) {
50f6fce8 3083 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3084 "Duplicate `context` entry in event class.");
e98a2d6e
PP
3085 ret = -EPERM;
3086 goto error;
3087 }
3088
5cd6d0e5 3089 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3090 _BT_LIST_FIRST_ENTRY(
3091 &node->u.ctf_expression.right,
3092 struct ctf_node, siblings),
5cd6d0e5 3093 &event_class->spec_context_fc);
e98a2d6e 3094 if (ret) {
50f6fce8 3095 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3096 "Cannot create event class's context field class.");
e98a2d6e
PP
3097 goto error;
3098 }
3099
5cd6d0e5 3100 BT_ASSERT(event_class->spec_context_fc);
e98a2d6e 3101 _SET(set, _EVENT_CONTEXT_SET);
2242b43d 3102 } else if (strcmp(left, "fields") == 0) {
e98a2d6e 3103 if (_IS_SET(set, _EVENT_FIELDS_SET)) {
50f6fce8 3104 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3105 "Duplicate `fields` entry in event class.");
e98a2d6e
PP
3106 ret = -EPERM;
3107 goto error;
3108 }
3109
5cd6d0e5 3110 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3111 _BT_LIST_FIRST_ENTRY(
3112 &node->u.ctf_expression.right,
3113 struct ctf_node, siblings),
5cd6d0e5 3114 &event_class->payload_fc);
e98a2d6e 3115 if (ret) {
50f6fce8 3116 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3117 "Cannot create event class's payload field class.");
e98a2d6e
PP
3118 goto error;
3119 }
3120
5cd6d0e5 3121 BT_ASSERT(event_class->payload_fc);
e98a2d6e 3122 _SET(set, _EVENT_FIELDS_SET);
2242b43d 3123 } else if (strcmp(left, "loglevel") == 0) {
c3c30b08 3124 uint64_t loglevel_value;
6da709aa 3125 bool is_log_level_known = true;
087cd0f5 3126 bt_event_class_log_level log_level;
e98a2d6e 3127
44c440bc 3128 if (_IS_SET(set, _EVENT_LOG_LEVEL_SET)) {
50f6fce8 3129 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "loglevel",
08da4f77 3130 "event class");
e98a2d6e
PP
3131 ret = -EPERM;
3132 goto error;
3133 }
3134
0746848c
PP
3135 ret = get_unary_unsigned(ctx,
3136 &node->u.ctf_expression.right, &loglevel_value);
e98a2d6e 3137 if (ret) {
50f6fce8 3138 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3139 "Unexpected unary expression for event class's `loglevel` attribute.");
e98a2d6e
PP
3140 ret = -EINVAL;
3141 goto error;
3142 }
cf76ce92
PP
3143
3144 switch (loglevel_value) {
3145 case 0:
50842bdc 3146 log_level = BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY;
cf76ce92
PP
3147 break;
3148 case 1:
50842bdc 3149 log_level = BT_EVENT_CLASS_LOG_LEVEL_ALERT;
cf76ce92
PP
3150 break;
3151 case 2:
50842bdc 3152 log_level = BT_EVENT_CLASS_LOG_LEVEL_CRITICAL;
cf76ce92
PP
3153 break;
3154 case 3:
50842bdc 3155 log_level = BT_EVENT_CLASS_LOG_LEVEL_ERROR;
cf76ce92
PP
3156 break;
3157 case 4:
50842bdc 3158 log_level = BT_EVENT_CLASS_LOG_LEVEL_WARNING;
cf76ce92
PP
3159 break;
3160 case 5:
50842bdc 3161 log_level = BT_EVENT_CLASS_LOG_LEVEL_NOTICE;
cf76ce92
PP
3162 break;
3163 case 6:
50842bdc 3164 log_level = BT_EVENT_CLASS_LOG_LEVEL_INFO;
cf76ce92
PP
3165 break;
3166 case 7:
50842bdc 3167 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM;
cf76ce92
PP
3168 break;
3169 case 8:
50842bdc 3170 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM;
cf76ce92
PP
3171 break;
3172 case 9:
50842bdc 3173 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS;
cf76ce92
PP
3174 break;
3175 case 10:
50842bdc 3176 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE;
cf76ce92
PP
3177 break;
3178 case 11:
50842bdc 3179 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT;
cf76ce92
PP
3180 break;
3181 case 12:
50842bdc 3182 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION;
cf76ce92
PP
3183 break;
3184 case 13:
50842bdc 3185 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE;
cf76ce92
PP
3186 break;
3187 case 14:
50842bdc 3188 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG;
cf76ce92
PP
3189 break;
3190 default:
6da709aa 3191 is_log_level_known = false;
f7b785ac 3192 _BT_COMP_LOGW_NODE(node, "Not setting event class's log level because its value is unknown: "
cf76ce92 3193 "log-level=%" PRIu64, loglevel_value);
c3c30b08 3194 }
cf76ce92 3195
6da709aa
JR
3196 if (is_log_level_known) {
3197 ctf_event_class_set_log_level(event_class, log_level);
c3c30b08 3198 }
cf76ce92 3199
44c440bc 3200 _SET(set, _EVENT_LOG_LEVEL_SET);
2242b43d 3201 } else if (strcmp(left, "model.emf.uri") == 0) {
e98a2d6e
PP
3202 char *right;
3203
3204 if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) {
50f6fce8 3205 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "model.emf.uri",
28973adf 3206 "event class");
e98a2d6e
PP
3207 ret = -EPERM;
3208 goto error;
3209 }
3210
1a6da3f9 3211 right = ctf_ast_concatenate_unary_strings(
e98a2d6e
PP
3212 &node->u.ctf_expression.right);
3213 if (!right) {
50f6fce8 3214 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3215 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
e98a2d6e
PP
3216 ret = -EINVAL;
3217 goto error;
3218 }
3219
cf76ce92 3220 if (strlen(right) == 0) {
f7b785ac 3221 _BT_COMP_LOGW_NODE(node,
cf76ce92
PP
3222 "Not setting event class's EMF URI because it's empty.");
3223 } else {
44c440bc
PP
3224 g_string_assign(event_class->emf_uri,
3225 right);
28973adf 3226 }
cf76ce92 3227
e98a2d6e
PP
3228 g_free(right);
3229 _SET(set, _EVENT_MODEL_EMF_URI_SET);
3230 } else {
f7b785ac 3231 _BT_COMP_LOGW_NODE(node,
28973adf 3232 "Unknown attribute in event class: "
08da4f77 3233 "attr-name=\"%s\"", left);
e98a2d6e
PP
3234 }
3235
3236 g_free(left);
3237 left = NULL;
3238 break;
3239 }
3240 default:
3241 ret = -EPERM;
3242 goto error;
3243 }
3244
44c440bc 3245 goto end;
e98a2d6e
PP
3246
3247error:
19bbdc9b 3248 g_free(left);
e98a2d6e 3249
44c440bc 3250end:
e98a2d6e
PP
3251 return ret;
3252}
3253
3254static
cf81cdae 3255char *get_event_decl_name(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
e98a2d6e
PP
3256{
3257 char *left = NULL;
3258 char *name = NULL;
3259 struct ctf_node *iter;
3260 struct bt_list_head *decl_list = &node->u.event.declaration_list;
3261
3262 bt_list_for_each_entry(iter, decl_list, siblings) {
3263 if (iter->type != NODE_CTF_EXPRESSION) {
3264 continue;
3265 }
3266
1a6da3f9 3267 left = ctf_ast_concatenate_unary_strings(&iter->u.ctf_expression.left);
e98a2d6e 3268 if (!left) {
50f6fce8 3269 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
28973adf 3270 "Cannot concatenate unary strings.");
e98a2d6e
PP
3271 goto error;
3272 }
3273
2242b43d 3274 if (strcmp(left, "name") == 0) {
1a6da3f9 3275 name = ctf_ast_concatenate_unary_strings(
e98a2d6e
PP
3276 &iter->u.ctf_expression.right);
3277 if (!name) {
50f6fce8 3278 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
28973adf 3279 "Unexpected unary expression for event class's `name` attribute.");
e98a2d6e
PP
3280 goto error;
3281 }
3282 }
3283
3284 g_free(left);
3285 left = NULL;
3286
3287 if (name) {
3288 break;
3289 }
3290 }
3291
3292 return name;
3293
3294error:
3295 g_free(left);
e98a2d6e
PP
3296 return NULL;
3297}
3298
3299static
cf81cdae 3300int visit_event_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
e98a2d6e
PP
3301{
3302 int ret = 0;
3303 int set = 0;
e98a2d6e 3304 struct ctf_node *iter;
44c440bc 3305 uint64_t stream_id = 0;
e98a2d6e 3306 char *event_name = NULL;
44c440bc
PP
3307 struct ctf_event_class *event_class = NULL;
3308 struct ctf_stream_class *stream_class = NULL;
e98a2d6e 3309 struct bt_list_head *decl_list = &node->u.event.declaration_list;
1e649dff 3310 bool pop_scope = false;
e98a2d6e
PP
3311
3312 if (node->visited) {
3313 goto end;
3314 }
3315
3316 node->visited = TRUE;
3317 event_name = get_event_decl_name(ctx, node);
3318 if (!event_name) {
50f6fce8 3319 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3320 "Missing `name` attribute in event class.");
e98a2d6e
PP
3321 ret = -EPERM;
3322 goto error;
3323 }
3324
44c440bc
PP
3325 event_class = ctf_event_class_create();
3326 BT_ASSERT(event_class);
3327 g_string_assign(event_class->name, event_name);
3328 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1e649dff
PP
3329 pop_scope = true;
3330
e98a2d6e
PP
3331 bt_list_for_each_entry(iter, decl_list, siblings) {
3332 ret = visit_event_decl_entry(ctx, iter, event_class,
3333 &stream_id, &set);
3334 if (ret) {
50f6fce8 3335 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit event class's entry: "
28973adf 3336 "ret=%d", ret);
e98a2d6e
PP
3337 goto error;
3338 }
3339 }
3340
3341 if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) {
1e649dff
PP
3342 /*
3343 * Allow missing stream_id if there is only a single
3344 * stream class.
3345 */
44c440bc 3346 switch (ctx->ctf_tc->stream_classes->len) {
e98a2d6e 3347 case 0:
1e649dff 3348 /* Create implicit stream class if there's none */
7b4b1ba2 3349 stream_id = 0;
44c440bc
PP
3350 stream_class = ctf_stream_class_create();
3351 BT_ASSERT(stream_class);
3352 stream_class->id = stream_id;
3353 g_ptr_array_add(ctx->ctf_tc->stream_classes,
3354 stream_class);
e98a2d6e
PP
3355 break;
3356 case 1:
1e649dff 3357 /* Single stream class: get its ID */
087cd0f5 3358 stream_class = (ctf_stream_class *) ctx->ctf_tc->stream_classes->pdata[0];
44c440bc 3359 stream_id = stream_class->id;
e98a2d6e
PP
3360 break;
3361 default:
50f6fce8 3362 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3363 "Missing `stream_id` attribute in event class.");
e98a2d6e
PP
3364 ret = -EPERM;
3365 goto error;
3366 }
3367 }
3368
1e649dff 3369 /* We have the stream ID now; get the stream class if found */
e98a2d6e 3370 if (!stream_class) {
44c440bc
PP
3371 stream_class = ctf_trace_class_borrow_stream_class_by_id(
3372 ctx->ctf_tc, stream_id);
1e649dff 3373 if (!stream_class) {
50f6fce8 3374 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3375 "Cannot find stream class at this point: "
08da4f77 3376 "id=%" PRId64, stream_id);
1e649dff
PP
3377 ret = -EINVAL;
3378 goto error;
3379 }
e98a2d6e
PP
3380 }
3381
f6ccaed9 3382 BT_ASSERT(stream_class);
1e649dff 3383
e98a2d6e
PP
3384 if (!_IS_SET(&set, _EVENT_ID_SET)) {
3385 /* Allow only one event without ID per stream */
44c440bc 3386 if (stream_class->event_classes->len != 0) {
50f6fce8 3387 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3388 "Missing `id` attribute in event class.");
e98a2d6e
PP
3389 ret = -EPERM;
3390 goto error;
3391 }
3392
3393 /* Automatic ID */
44c440bc 3394 event_class->id = 0;
e98a2d6e
PP
3395 }
3396
44c440bc
PP
3397 if (ctf_stream_class_borrow_event_class_by_id(stream_class,
3398 event_class->id)) {
50f6fce8 3399 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3400 "Duplicate event class (same ID) in the same stream class: "
44c440bc 3401 "id=%" PRId64, event_class->id);
e98a2d6e
PP
3402 ret = -EEXIST;
3403 goto error;
3404 }
3405
44c440bc
PP
3406 ctf_stream_class_append_event_class(stream_class, event_class);
3407 event_class = NULL;
1e649dff 3408 goto end;
e98a2d6e
PP
3409
3410error:
44c440bc
PP
3411 ctf_event_class_destroy(event_class);
3412 event_class = NULL;
3413
3414 if (ret >= 0) {
3415 ret = -1;
3416 }
e98a2d6e 3417
1e649dff
PP
3418end:
3419 if (pop_scope) {
3420 ctx_pop_scope(ctx);
3421 }
e98a2d6e 3422
19bbdc9b 3423 g_free(event_name);
44c440bc 3424
e98a2d6e
PP
3425 return ret;
3426}
3427
56b43721 3428static
cf81cdae 3429int auto_map_field_to_trace_clock_class(struct ctf_visitor_generate_ir *ctx,
5cd6d0e5 3430 struct ctf_field_class *fc)
56b43721 3431{
0f2d58c9 3432 struct ctf_clock_class *clock_class_to_map_to = NULL;
087cd0f5 3433 struct ctf_field_class_int *int_fc = ctf_field_class_as_int(fc);
56b43721 3434 int ret = 0;
44c440bc
PP
3435 uint64_t clock_class_count;
3436
5cd6d0e5 3437 if (!fc) {
44c440bc
PP
3438 goto end;
3439 }
56b43721 3440
864cad70
PP
3441 if (fc->type != CTF_FIELD_CLASS_TYPE_INT &&
3442 fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
56b43721
PP
3443 goto end;
3444 }
3445
5cd6d0e5 3446 if (int_fc->mapped_clock_class) {
44c440bc 3447 /* Already mapped */
56b43721
PP
3448 goto end;
3449 }
3450
44c440bc 3451 clock_class_count = ctx->ctf_tc->clock_classes->len;
7bf5af54
PP
3452
3453 switch (clock_class_count) {
3454 case 0:
3455 /*
44c440bc
PP
3456 * No clock class exists in the trace at this point. Create an
3457 * implicit one at 1 GHz, named `default`, and use this clock
3458 * class.
7bf5af54 3459 */
0f2d58c9 3460 clock_class_to_map_to = ctf_clock_class_create();
44c440bc 3461 BT_ASSERT(clock_class_to_map_to);
0f2d58c9
PP
3462 clock_class_to_map_to->frequency = UINT64_C(1000000000);
3463 g_string_assign(clock_class_to_map_to->name, "default");
44c440bc
PP
3464 BT_ASSERT(ret == 0);
3465 g_ptr_array_add(ctx->ctf_tc->clock_classes,
398454ed 3466 clock_class_to_map_to);
7bf5af54
PP
3467 break;
3468 case 1:
3469 /*
44c440bc
PP
3470 * Only one clock class exists in the trace at this point: use
3471 * this one.
7bf5af54 3472 */
087cd0f5 3473 clock_class_to_map_to = (ctf_clock_class *) ctx->ctf_tc->clock_classes->pdata[0];
7bf5af54
PP
3474 break;
3475 default:
3476 /*
44c440bc
PP
3477 * Timestamp field not mapped to a clock class and there's more
3478 * than one clock class in the trace: this is an error.
7bf5af54 3479 */
50f6fce8 3480 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Timestamp field found with no mapped clock class, "
7bf5af54
PP
3481 "but there's more than one clock class in the trace at this point.");
3482 ret = -1;
56b43721
PP
3483 goto end;
3484 }
3485
f6ccaed9 3486 BT_ASSERT(clock_class_to_map_to);
398454ed 3487 int_fc->mapped_clock_class = clock_class_to_map_to;
56b43721 3488
7bf5af54 3489end:
7bf5af54
PP
3490 return ret;
3491}
56b43721 3492
7bf5af54 3493static
cf81cdae 3494int auto_map_fields_to_trace_clock_class(struct ctf_visitor_generate_ir *ctx,
5cd6d0e5 3495 struct ctf_field_class *root_fc, const char *field_name)
7bf5af54
PP
3496{
3497 int ret = 0;
44c440bc 3498 uint64_t i, count;
087cd0f5
SM
3499 struct ctf_field_class_struct *struct_fc = (ctf_field_class_struct *) root_fc;
3500 struct ctf_field_class_variant *var_fc = (ctf_field_class_variant *) root_fc;
56b43721 3501
5cd6d0e5 3502 if (!root_fc) {
7bf5af54
PP
3503 goto end;
3504 }
56b43721 3505
864cad70
PP
3506 if (root_fc->type != CTF_FIELD_CLASS_TYPE_STRUCT &&
3507 root_fc->type != CTF_FIELD_CLASS_TYPE_VARIANT) {
7bf5af54
PP
3508 goto end;
3509 }
3510
864cad70 3511 if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
5cd6d0e5 3512 count = struct_fc->members->len;
7bf5af54 3513 } else {
5cd6d0e5 3514 count = var_fc->options->len;
7bf5af54
PP
3515 }
3516
7bf5af54 3517 for (i = 0; i < count; i++) {
5cd6d0e5 3518 struct ctf_named_field_class *named_fc = NULL;
7bf5af54 3519
864cad70 3520 if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
5cd6d0e5
PP
3521 named_fc = ctf_field_class_struct_borrow_member_by_index(
3522 struct_fc, i);
864cad70 3523 } else if (root_fc->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
5cd6d0e5
PP
3524 named_fc = ctf_field_class_variant_borrow_option_by_index(
3525 var_fc, i);
fba9c0c1 3526 } else {
498e7994 3527 bt_common_abort();
7bf5af54
PP
3528 }
3529
5cd6d0e5 3530 if (strcmp(named_fc->name->str, field_name) == 0) {
44c440bc 3531 ret = auto_map_field_to_trace_clock_class(ctx,
5cd6d0e5 3532 named_fc->fc);
7bf5af54 3533 if (ret) {
50f6fce8 3534 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot automatically map field to trace's clock class: "
7bf5af54 3535 "field-name=\"%s\"", field_name);
7bf5af54 3536 goto end;
56b43721
PP
3537 }
3538 }
3539
5cd6d0e5 3540 ret = auto_map_fields_to_trace_clock_class(ctx, named_fc->fc,
44c440bc 3541 field_name);
7bf5af54 3542 if (ret) {
50f6fce8 3543 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot automatically map structure or variant field class's fields to trace's clock class: "
7bf5af54 3544 "field-name=\"%s\", root-field-name=\"%s\"",
5cd6d0e5 3545 field_name, named_fc->name->str);
7bf5af54
PP
3546 goto end;
3547 }
56b43721
PP
3548 }
3549
3550end:
56b43721
PP
3551 return ret;
3552}
3553
e98a2d6e 3554static
cf81cdae 3555int visit_stream_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node,
44c440bc 3556 struct ctf_stream_class *stream_class, int *set)
e98a2d6e
PP
3557{
3558 int ret = 0;
3559 char *left = NULL;
e98a2d6e
PP
3560
3561 switch (node->type) {
3562 case NODE_TYPEDEF:
5cd6d0e5
PP
3563 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3564 &node->u.field_class_def.field_class_declarators);
e98a2d6e 3565 if (ret) {
50f6fce8 3566 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3567 "Cannot add field class found in stream class.");
e98a2d6e
PP
3568 goto error;
3569 }
3570 break;
3571 case NODE_TYPEALIAS:
5cd6d0e5
PP
3572 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3573 node->u.field_class_alias.alias);
e98a2d6e 3574 if (ret) {
50f6fce8 3575 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3576 "Cannot add field class alias found in stream class.");
e98a2d6e
PP
3577 goto error;
3578 }
3579 break;
3580 case NODE_CTF_EXPRESSION:
3581 {
1a6da3f9 3582 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
e98a2d6e 3583 if (!left) {
50f6fce8 3584 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
e98a2d6e
PP
3585 ret = -EINVAL;
3586 goto error;
3587 }
3588
2242b43d 3589 if (strcmp(left, "id") == 0) {
e98a2d6e 3590 int64_t id;
e98a2d6e
PP
3591
3592 if (_IS_SET(set, _STREAM_ID_SET)) {
50f6fce8 3593 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "id",
28973adf 3594 "stream declaration");
e98a2d6e
PP
3595 ret = -EPERM;
3596 goto error;
3597 }
3598
0746848c
PP
3599 ret = get_unary_unsigned(ctx,
3600 &node->u.ctf_expression.right,
e98a2d6e 3601 (uint64_t *) &id);
44c440bc 3602
5eae0c3c
JG
3603 /* Only read "id" if get_unary_unsigned() succeeded. */
3604 if (ret || (!ret && id < 0)) {
50f6fce8 3605 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3606 "Unexpected unary expression for stream class's `id` attribute.");
e98a2d6e
PP
3607 ret = -EINVAL;
3608 goto error;
3609 }
3610
44c440bc
PP
3611 if (ctf_trace_class_borrow_stream_class_by_id(
3612 ctx->ctf_tc, id)) {
50f6fce8 3613 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3614 "Duplicate stream class (same ID): id=%" PRId64,
e98a2d6e
PP
3615 id);
3616 ret = -EEXIST;
3617 goto error;
3618 }
3619
44c440bc 3620 stream_class->id = id;
e98a2d6e 3621 _SET(set, _STREAM_ID_SET);
2242b43d 3622 } else if (strcmp(left, "event.header") == 0) {
e98a2d6e 3623 if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) {
50f6fce8 3624 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3625 "Duplicate `event.header` entry in stream class.");
e98a2d6e
PP
3626 ret = -EPERM;
3627 goto error;
3628 }
3629
5cd6d0e5 3630 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3631 _BT_LIST_FIRST_ENTRY(
3632 &node->u.ctf_expression.right,
3633 struct ctf_node, siblings),
5cd6d0e5 3634 &stream_class->event_header_fc);
e98a2d6e 3635 if (ret) {
50f6fce8 3636 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3637 "Cannot create stream class's event header field class.");
e98a2d6e
PP
3638 goto error;
3639 }
3640
5cd6d0e5 3641 BT_ASSERT(stream_class->event_header_fc);
56b43721 3642 ret = auto_map_fields_to_trace_clock_class(ctx,
5cd6d0e5 3643 stream_class->event_header_fc, "timestamp");
56b43721 3644 if (ret) {
50f6fce8 3645 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3646 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
56b43721
PP
3647 goto error;
3648 }
e98a2d6e 3649
e98a2d6e 3650 _SET(set, _STREAM_EVENT_HEADER_SET);
2242b43d 3651 } else if (strcmp(left, "event.context") == 0) {
e98a2d6e 3652 if (_IS_SET(set, _STREAM_EVENT_CONTEXT_SET)) {
50f6fce8 3653 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3654 "Duplicate `event.context` entry in stream class.");
e98a2d6e
PP
3655 ret = -EPERM;
3656 goto error;
3657 }
3658
5cd6d0e5 3659 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3660 _BT_LIST_FIRST_ENTRY(
3661 &node->u.ctf_expression.right,
3662 struct ctf_node, siblings),
5cd6d0e5 3663 &stream_class->event_common_context_fc);
e98a2d6e 3664 if (ret) {
50f6fce8 3665 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3666 "Cannot create stream class's event context field class.");
e98a2d6e
PP
3667 goto error;
3668 }
3669
5cd6d0e5 3670 BT_ASSERT(stream_class->event_common_context_fc);
e98a2d6e 3671 _SET(set, _STREAM_EVENT_CONTEXT_SET);
2242b43d 3672 } else if (strcmp(left, "packet.context") == 0) {
e98a2d6e 3673 if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) {
50f6fce8 3674 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3675 "Duplicate `packet.context` entry in stream class.");
e98a2d6e
PP
3676 ret = -EPERM;
3677 goto error;
3678 }
3679
5cd6d0e5 3680 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3681 _BT_LIST_FIRST_ENTRY(
3682 &node->u.ctf_expression.right,
3683 struct ctf_node, siblings),
5cd6d0e5 3684 &stream_class->packet_context_fc);
e98a2d6e 3685 if (ret) {
50f6fce8 3686 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3687 "Cannot create stream class's packet context field class.");
e98a2d6e
PP
3688 goto error;
3689 }
3690
5cd6d0e5 3691 BT_ASSERT(stream_class->packet_context_fc);
56b43721 3692 ret = auto_map_fields_to_trace_clock_class(ctx,
5cd6d0e5 3693 stream_class->packet_context_fc,
44c440bc 3694 "timestamp_begin");
7bf5af54 3695 if (ret) {
50f6fce8 3696 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3697 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
7bf5af54
PP
3698 goto error;
3699 }
3700
3701 ret = auto_map_fields_to_trace_clock_class(ctx,
5cd6d0e5 3702 stream_class->packet_context_fc,
44c440bc 3703 "timestamp_end");
56b43721 3704 if (ret) {
50f6fce8 3705 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3706 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
56b43721
PP
3707 goto error;
3708 }
e98a2d6e 3709
e98a2d6e
PP
3710 _SET(set, _STREAM_PACKET_CONTEXT_SET);
3711 } else {
f7b785ac 3712 _BT_COMP_LOGW_NODE(node,
28973adf 3713 "Unknown attribute in stream class: "
08da4f77 3714 "attr-name=\"%s\"", left);
e98a2d6e
PP
3715 }
3716
3717 g_free(left);
3718 left = NULL;
3719 break;
3720 }
3721
3722 default:
3723 ret = -EPERM;
3724 goto error;
3725 }
3726
3727 return 0;
3728
3729error:
3730 g_free(left);
e98a2d6e
PP
3731 return ret;
3732}
3733
3734static
cf81cdae 3735int visit_stream_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
e98a2d6e 3736{
e98a2d6e
PP
3737 int set = 0;
3738 int ret = 0;
3739 struct ctf_node *iter;
44c440bc 3740 struct ctf_stream_class *stream_class = NULL;
e98a2d6e
PP
3741 struct bt_list_head *decl_list = &node->u.stream.declaration_list;
3742
3743 if (node->visited) {
3744 goto end;
3745 }
3746
3747 node->visited = TRUE;
44c440bc
PP
3748 stream_class = ctf_stream_class_create();
3749 BT_ASSERT(stream_class);
3750 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
e98a2d6e
PP
3751
3752 bt_list_for_each_entry(iter, decl_list, siblings) {
3753 ret = visit_stream_decl_entry(ctx, iter, stream_class, &set);
3754 if (ret) {
50f6fce8 3755 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
28973adf
PP
3756 "Cannot visit stream class's entry: "
3757 "ret=%d", ret);
e98a2d6e
PP
3758 ctx_pop_scope(ctx);
3759 goto error;
3760 }
3761 }
3762
3763 ctx_pop_scope(ctx);
3764
3765 if (_IS_SET(&set, _STREAM_ID_SET)) {
44c440bc 3766 /* Check that packet header has `stream_id` field */
5cd6d0e5 3767 struct ctf_named_field_class *named_fc = NULL;
e98a2d6e 3768
5cd6d0e5 3769 if (!ctx->ctf_tc->packet_header_fc) {
50f6fce8 3770 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3771 "Stream class has a `id` attribute, "
5cd6d0e5 3772 "but trace has no packet header field class.");
d6701381 3773 ret = -EINVAL;
e98a2d6e
PP
3774 goto error;
3775 }
3776
5cd6d0e5 3777 named_fc = ctf_field_class_struct_borrow_member_by_name(
087cd0f5 3778 ctf_field_class_as_struct(ctx->ctf_tc->packet_header_fc), "stream_id");
5cd6d0e5 3779 if (!named_fc) {
50f6fce8 3780 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3781 "Stream class has a `id` attribute, "
5cd6d0e5 3782 "but trace's packet header field class has no `stream_id` field.");
d6701381 3783 ret = -EINVAL;
e98a2d6e
PP
3784 goto error;
3785 }
3786
864cad70
PP
3787 if (named_fc->fc->type != CTF_FIELD_CLASS_TYPE_INT &&
3788 named_fc->fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
50f6fce8 3789 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3790 "Stream class has a `id` attribute, "
5cd6d0e5 3791 "but trace's packet header field class's `stream_id` field is not an integer field class.");
d6701381 3792 ret = -EINVAL;
e98a2d6e
PP
3793 goto error;
3794 }
e98a2d6e
PP
3795 } else {
3796 /* Allow only _one_ ID-less stream */
44c440bc 3797 if (ctx->ctf_tc->stream_classes->len != 0) {
50f6fce8 3798 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3799 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
e98a2d6e
PP
3800 ret = -EPERM;
3801 goto error;
3802 }
3803
3804 /* Automatic ID: 0 */
44c440bc 3805 stream_class->id = 0;
e98a2d6e
PP
3806 }
3807
1e649dff
PP
3808 /*
3809 * Make sure that this stream class's ID is currently unique in
3810 * the trace.
3811 */
44c440bc
PP
3812 if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc,
3813 stream_class->id)) {
50f6fce8 3814 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3815 "Duplicate stream class (same ID): id=%" PRId64,
44c440bc 3816 stream_class->id);
1e649dff
PP
3817 ret = -EINVAL;
3818 goto error;
3819 }
3820
44c440bc 3821 g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class);
e98a2d6e 3822 stream_class = NULL;
1e649dff 3823 goto end;
e98a2d6e
PP
3824
3825error:
44c440bc
PP
3826 ctf_stream_class_destroy(stream_class);
3827 stream_class = NULL;
e98a2d6e 3828
1e649dff 3829end:
e98a2d6e
PP
3830 return ret;
3831}
3832
3833static
cf81cdae
SM
3834int visit_trace_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node,
3835 int *set)
e98a2d6e
PP
3836{
3837 int ret = 0;
3838 char *left = NULL;
44c440bc 3839 uint64_t val;
e98a2d6e
PP
3840
3841 switch (node->type) {
3842 case NODE_TYPEDEF:
5cd6d0e5
PP
3843 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3844 &node->u.field_class_def.field_class_declarators);
e98a2d6e 3845 if (ret) {
50f6fce8 3846 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3847 "Cannot add field class found in trace (`trace` block).");
e98a2d6e
PP
3848 goto error;
3849 }
3850 break;
3851 case NODE_TYPEALIAS:
5cd6d0e5
PP
3852 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3853 node->u.field_class_alias.alias);
e98a2d6e 3854 if (ret) {
50f6fce8 3855 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3856 "Cannot add field class alias found in trace (`trace` block).");
e98a2d6e
PP
3857 goto error;
3858 }
3859 break;
3860 case NODE_CTF_EXPRESSION:
3861 {
1a6da3f9 3862 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
e98a2d6e 3863 if (!left) {
50f6fce8 3864 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
e98a2d6e
PP
3865 ret = -EINVAL;
3866 goto error;
3867 }
3868
2242b43d 3869 if (strcmp(left, "major") == 0) {
e98a2d6e 3870 if (_IS_SET(set, _TRACE_MAJOR_SET)) {
50f6fce8 3871 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "major", "trace");
e98a2d6e
PP
3872 ret = -EPERM;
3873 goto error;
3874 }
3875
0746848c
PP
3876 ret = get_unary_unsigned(ctx,
3877 &node->u.ctf_expression.right, &val);
e98a2d6e 3878 if (ret) {
50f6fce8 3879 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3880 "Unexpected unary expression for trace's `major` attribute.");
e98a2d6e
PP
3881 ret = -EINVAL;
3882 goto error;
3883 }
3884
44c440bc 3885 if (val != 1) {
50f6fce8 3886 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
44c440bc 3887 "Invalid trace's `minor` attribute: expecting 1.");
d6701381 3888 ret = -EINVAL;
44c440bc
PP
3889 goto error;
3890 }
3891
3892 ctx->ctf_tc->major = val;
e98a2d6e 3893 _SET(set, _TRACE_MAJOR_SET);
2242b43d 3894 } else if (strcmp(left, "minor") == 0) {
e98a2d6e 3895 if (_IS_SET(set, _TRACE_MINOR_SET)) {
50f6fce8 3896 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "minor", "trace");
e98a2d6e
PP
3897 ret = -EPERM;
3898 goto error;
3899 }
3900
0746848c
PP
3901 ret = get_unary_unsigned(ctx,
3902 &node->u.ctf_expression.right, &val);
e98a2d6e 3903 if (ret) {
50f6fce8 3904 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3905 "Unexpected unary expression for trace's `minor` attribute.");
e98a2d6e
PP
3906 ret = -EINVAL;
3907 goto error;
3908 }
3909
44c440bc 3910 if (val != 8) {
50f6fce8 3911 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
44c440bc 3912 "Invalid trace's `minor` attribute: expecting 8.");
d6701381 3913 ret = -EINVAL;
44c440bc
PP
3914 goto error;
3915 }
3916
3917 ctx->ctf_tc->minor = val;
e98a2d6e 3918 _SET(set, _TRACE_MINOR_SET);
2242b43d 3919 } else if (strcmp(left, "uuid") == 0) {
e98a2d6e 3920 if (_IS_SET(set, _TRACE_UUID_SET)) {
50f6fce8 3921 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "uuid", "trace");
e98a2d6e
PP
3922 ret = -EPERM;
3923 goto error;
3924 }
3925
0746848c
PP
3926 ret = get_unary_uuid(ctx,
3927 &node->u.ctf_expression.right,
44c440bc 3928 ctx->ctf_tc->uuid);
e98a2d6e 3929 if (ret) {
50f6fce8 3930 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3931 "Invalid trace's `uuid` attribute.");
e98a2d6e
PP
3932 goto error;
3933 }
3934
44c440bc 3935 ctx->ctf_tc->is_uuid_set = true;
e98a2d6e 3936 _SET(set, _TRACE_UUID_SET);
2242b43d 3937 } else if (strcmp(left, "byte_order") == 0) {
44c440bc 3938 /* Default byte order is already known at this stage */
e98a2d6e 3939 if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) {
50f6fce8 3940 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "byte_order",
08da4f77 3941 "trace");
e98a2d6e
PP
3942 ret = -EPERM;
3943 goto error;
3944 }
3945
e2bd7d40 3946 BT_ASSERT(ctx->ctf_tc->default_byte_order != CTF_BYTE_ORDER_UNKNOWN);
e98a2d6e 3947 _SET(set, _TRACE_BYTE_ORDER_SET);
2242b43d 3948 } else if (strcmp(left, "packet.header") == 0) {
e98a2d6e 3949 if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) {
50f6fce8 3950 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 3951 "Duplicate `packet.header` entry in trace.");
e98a2d6e
PP
3952 ret = -EPERM;
3953 goto error;
3954 }
3955
5cd6d0e5 3956 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3957 _BT_LIST_FIRST_ENTRY(
3958 &node->u.ctf_expression.right,
3959 struct ctf_node, siblings),
5cd6d0e5 3960 &ctx->ctf_tc->packet_header_fc);
e98a2d6e 3961 if (ret) {
50f6fce8 3962 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
5cd6d0e5 3963 "Cannot create trace's packet header field class.");
e98a2d6e
PP
3964 goto error;
3965 }
3966
5cd6d0e5 3967 BT_ASSERT(ctx->ctf_tc->packet_header_fc);
e98a2d6e
PP
3968 _SET(set, _TRACE_PACKET_HEADER_SET);
3969 } else {
f7b785ac 3970 _BT_COMP_LOGW_NODE(node,
28973adf 3971 "Unknown attribute in stream class: "
08da4f77 3972 "attr-name=\"%s\"", left);
e98a2d6e
PP
3973 }
3974
3975 g_free(left);
3976 left = NULL;
3977 break;
3978 }
3979 default:
50f6fce8 3980 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unknown expression in trace.");
e98a2d6e
PP
3981 ret = -EINVAL;
3982 goto error;
3983 }
3984
3985 return 0;
3986
3987error:
3988 g_free(left);
e98a2d6e
PP
3989 return ret;
3990}
3991
3992static
cf81cdae 3993int visit_trace_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
e98a2d6e
PP
3994{
3995 int ret = 0;
3996 int set = 0;
3997 struct ctf_node *iter;
3998 struct bt_list_head *decl_list = &node->u.trace.declaration_list;
3999
4000 if (node->visited) {
4001 goto end;
4002 }
4003
4004 node->visited = TRUE;
4005
4006 if (ctx->is_trace_visited) {
50f6fce8 4007 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate trace (`trace` block).");
e98a2d6e
PP
4008 ret = -EEXIST;
4009 goto error;
4010 }
4011
44c440bc 4012 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
e98a2d6e
PP
4013
4014 bt_list_for_each_entry(iter, decl_list, siblings) {
4015 ret = visit_trace_decl_entry(ctx, iter, &set);
4016 if (ret) {
50f6fce8 4017 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit trace's entry (`trace` block): "
28973adf 4018 "ret=%d", ret);
e98a2d6e
PP
4019 ctx_pop_scope(ctx);
4020 goto error;
4021 }
4022 }
4023
4024 ctx_pop_scope(ctx);
4025
4026 if (!_IS_SET(&set, _TRACE_MAJOR_SET)) {
50f6fce8 4027 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 4028 "Missing `major` attribute in trace (`trace` block).");
e98a2d6e
PP
4029 ret = -EPERM;
4030 goto error;
4031 }
4032
4033 if (!_IS_SET(&set, _TRACE_MINOR_SET)) {
50f6fce8 4034 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 4035 "Missing `minor` attribute in trace (`trace` block).");
e98a2d6e
PP
4036 ret = -EPERM;
4037 goto error;
4038 }
4039
4040 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
50f6fce8 4041 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 4042 "Missing `byte_order` attribute in trace (`trace` block).");
e98a2d6e
PP
4043 ret = -EPERM;
4044 goto error;
4045 }
4046
44c440bc 4047 ctx->is_trace_visited = true;
e98a2d6e
PP
4048
4049end:
4050 return 0;
4051
4052error:
4053 return ret;
4054}
4055
4056static
cf81cdae 4057int visit_env(struct ctf_visitor_generate_ir *ctx, struct ctf_node *node)
e98a2d6e
PP
4058{
4059 int ret = 0;
4060 char *left = NULL;
4061 struct ctf_node *entry_node;
4062 struct bt_list_head *decl_list = &node->u.env.declaration_list;
4063
4064 if (node->visited) {
4065 goto end;
4066 }
4067
4068 node->visited = TRUE;
4069
4070 bt_list_for_each_entry(entry_node, decl_list, siblings) {
4071 struct bt_list_head *right_head =
4072 &entry_node->u.ctf_expression.right;
4073
4074 if (entry_node->type != NODE_CTF_EXPRESSION) {
50f6fce8 4075 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 4076 "Wrong expression in environment entry: "
08da4f77 4077 "node-type=%d", entry_node->type);
e98a2d6e
PP
4078 ret = -EPERM;
4079 goto error;
4080 }
4081
1a6da3f9 4082 left = ctf_ast_concatenate_unary_strings(
e98a2d6e
PP
4083 &entry_node->u.ctf_expression.left);
4084 if (!left) {
50f6fce8 4085 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 4086 "Cannot get environment entry's name.");
e98a2d6e
PP
4087 ret = -EINVAL;
4088 goto error;
4089 }
4090
4091 if (is_unary_string(right_head)) {
1a6da3f9 4092 char *right = ctf_ast_concatenate_unary_strings(right_head);
e98a2d6e
PP
4093
4094 if (!right) {
50f6fce8 4095 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 4096 "Unexpected unary expression for environment entry's value: "
08da4f77 4097 "name=\"%s\"", left);
e98a2d6e
PP
4098 ret = -EINVAL;
4099 goto error;
4100 }
4101
7bf5af54
PP
4102 if (strcmp(left, "tracer_name") == 0) {
4103 if (strncmp(right, "lttng", 5) == 0) {
f7b785ac 4104 BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: "
7bf5af54
PP
4105 "tracer-name=\"%s\"",
4106 left, right);
44c440bc 4107 ctx->is_lttng = true;
f4421ff3
PP
4108 }
4109 }
4110
44c440bc
PP
4111 ctf_trace_class_append_env_entry(ctx->ctf_tc,
4112 left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR,
4113 right, 0);
e98a2d6e 4114 g_free(right);
e98a2d6e
PP
4115 } else if (is_unary_unsigned(right_head) ||
4116 is_unary_signed(right_head)) {
4117 int64_t v;
4118
4119 if (is_unary_unsigned(right_head)) {
0746848c 4120 ret = get_unary_unsigned(ctx, right_head,
e98a2d6e
PP
4121 (uint64_t *) &v);
4122 } else {
4123 ret = get_unary_signed(right_head, &v);
4124 }
4125 if (ret) {
50f6fce8 4126 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 4127 "Unexpected unary expression for environment entry's value: "
08da4f77 4128 "name=\"%s\"", left);
e98a2d6e
PP
4129 ret = -EINVAL;
4130 goto error;
4131 }
4132
44c440bc
PP
4133 ctf_trace_class_append_env_entry(ctx->ctf_tc,
4134 left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT,
4135 NULL, v);
e98a2d6e 4136 } else {
f7b785ac 4137 _BT_COMP_LOGW_NODE(entry_node,
28973adf 4138 "Environment entry has unknown type: "
08da4f77 4139 "name=\"%s\"", left);
e98a2d6e
PP
4140 }
4141
4142 g_free(left);
4143 left = NULL;
4144 }
4145
4146end:
4147 return 0;
4148
4149error:
4150 g_free(left);
e98a2d6e
PP
4151 return ret;
4152}
4153
4154static
cf81cdae 4155int set_trace_byte_order(struct ctf_visitor_generate_ir *ctx, struct ctf_node *trace_node)
e98a2d6e
PP
4156{
4157 int ret = 0;
4158 int set = 0;
4159 char *left = NULL;
4160 struct ctf_node *node;
4161 struct bt_list_head *decl_list = &trace_node->u.trace.declaration_list;
4162
4163 bt_list_for_each_entry(node, decl_list, siblings) {
4164 if (node->type == NODE_CTF_EXPRESSION) {
4165 struct ctf_node *right_node;
4166
1a6da3f9 4167 left = ctf_ast_concatenate_unary_strings(
e98a2d6e
PP
4168 &node->u.ctf_expression.left);
4169 if (!left) {
50f6fce8 4170 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 4171 "Cannot concatenate unary strings.");
e98a2d6e
PP
4172 ret = -EINVAL;
4173 goto error;
4174 }
4175
2242b43d 4176 if (strcmp(left, "byte_order") == 0) {
44c440bc 4177 enum ctf_byte_order bo;
e98a2d6e
PP
4178
4179 if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
50f6fce8 4180 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "byte_order",
08da4f77 4181 "trace");
e98a2d6e
PP
4182 ret = -EPERM;
4183 goto error;
4184 }
4185
4186 _SET(&set, _TRACE_BYTE_ORDER_SET);
4187 right_node = _BT_LIST_FIRST_ENTRY(
4188 &node->u.ctf_expression.right,
4189 struct ctf_node, siblings);
0746848c
PP
4190 bo = byte_order_from_unary_expr(ctx,
4191 right_node);
e2bd7d40 4192 if (bo == CTF_BYTE_ORDER_UNKNOWN) {
50f6fce8 4193 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf
PP
4194 "Invalid `byte_order` attribute in trace (`trace` block): "
4195 "expecting `le`, `be`, or `network`.");
e98a2d6e
PP
4196 ret = -EINVAL;
4197 goto error;
44c440bc 4198 } else if (bo == CTF_BYTE_ORDER_DEFAULT) {
50f6fce8 4199 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 4200 "Invalid `byte_order` attribute in trace (`trace` block): "
08da4f77 4201 "cannot be set to `native` here.");
e98a2d6e
PP
4202 ret = -EPERM;
4203 goto error;
4204 }
4205
44c440bc 4206 ctx->ctf_tc->default_byte_order = bo;
e98a2d6e
PP
4207 }
4208
4209 g_free(left);
4210 left = NULL;
4211 }
4212 }
4213
4214 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
50f6fce8 4215 _BT_COMP_LOGE_APPEND_CAUSE_NODE(trace_node,
28973adf 4216 "Missing `byte_order` attribute in trace (`trace` block).");
e98a2d6e
PP
4217 ret = -EINVAL;
4218 goto error;
4219 }
4220
4221 return 0;
4222
4223error:
4224 g_free(left);
e98a2d6e
PP
4225 return ret;
4226}
4227
4228static
cf81cdae 4229int visit_clock_decl_entry(struct ctf_visitor_generate_ir *ctx, struct ctf_node *entry_node,
0f2d58c9 4230 struct ctf_clock_class *clock, int *set, int64_t *offset_seconds,
44c440bc 4231 uint64_t *offset_cycles)
e98a2d6e
PP
4232{
4233 int ret = 0;
4234 char *left = NULL;
4235
4236 if (entry_node->type != NODE_CTF_EXPRESSION) {
50f6fce8 4237 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf
PP
4238 "Unexpected node type: node-type=%d",
4239 entry_node->type);
e98a2d6e
PP
4240 ret = -EPERM;
4241 goto error;
4242 }
4243
1a6da3f9 4244 left = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.left);
e98a2d6e 4245 if (!left) {
50f6fce8 4246 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Cannot concatenate unary strings.");
e98a2d6e
PP
4247 ret = -EINVAL;
4248 goto error;
4249 }
4250
2242b43d 4251 if (strcmp(left, "name") == 0) {
e98a2d6e
PP
4252 char *right;
4253
4254 if (_IS_SET(set, _CLOCK_NAME_SET)) {
50f6fce8 4255 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "name", "clock class");
e98a2d6e
PP
4256 ret = -EPERM;
4257 goto error;
4258 }
4259
1a6da3f9 4260 right = ctf_ast_concatenate_unary_strings(
e98a2d6e
PP
4261 &entry_node->u.ctf_expression.right);
4262 if (!right) {
50f6fce8 4263 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 4264 "Unexpected unary expression for clock class's `name` attribute.");
e98a2d6e
PP
4265 ret = -EINVAL;
4266 goto error;
4267 }
4268
0f2d58c9 4269 g_string_assign(clock->name, right);
e98a2d6e
PP
4270 g_free(right);
4271 _SET(set, _CLOCK_NAME_SET);
2242b43d 4272 } else if (strcmp(left, "uuid") == 0) {
6162e6b7 4273 bt_uuid_t uuid;
e98a2d6e
PP
4274
4275 if (_IS_SET(set, _CLOCK_UUID_SET)) {
50f6fce8 4276 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "uuid", "clock class");
e98a2d6e
PP
4277 ret = -EPERM;
4278 goto error;
4279 }
4280
0746848c
PP
4281 ret = get_unary_uuid(ctx, &entry_node->u.ctf_expression.right,
4282 uuid);
e98a2d6e 4283 if (ret) {
50f6fce8 4284 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 4285 "Invalid clock class's `uuid` attribute.");
e98a2d6e
PP
4286 goto error;
4287 }
4288
0f2d58c9 4289 clock->has_uuid = true;
6162e6b7 4290 bt_uuid_copy(clock->uuid, uuid);
e98a2d6e 4291 _SET(set, _CLOCK_UUID_SET);
2242b43d 4292 } else if (strcmp(left, "description") == 0) {
e98a2d6e
PP
4293 char *right;
4294
4295 if (_IS_SET(set, _CLOCK_DESCRIPTION_SET)) {
50f6fce8 4296 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "description",
28973adf 4297 "clock class");
e98a2d6e
PP
4298 ret = -EPERM;
4299 goto error;
4300 }
4301
1a6da3f9 4302 right = ctf_ast_concatenate_unary_strings(
e98a2d6e
PP
4303 &entry_node->u.ctf_expression.right);
4304 if (!right) {
50f6fce8 4305 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 4306 "Unexpected unary expression for clock class's `description` attribute.");
e98a2d6e
PP
4307 ret = -EINVAL;
4308 goto error;
4309 }
4310
0f2d58c9 4311 g_string_assign(clock->description, right);
e98a2d6e
PP
4312 g_free(right);
4313 _SET(set, _CLOCK_DESCRIPTION_SET);
2242b43d 4314 } else if (strcmp(left, "freq") == 0) {
44c440bc 4315 uint64_t freq = UINT64_C(-1);
e98a2d6e
PP
4316
4317 if (_IS_SET(set, _CLOCK_FREQ_SET)) {
50f6fce8 4318 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "freq", "clock class");
e98a2d6e
PP
4319 ret = -EPERM;
4320 goto error;
4321 }
4322
0746848c 4323 ret = get_unary_unsigned(ctx,
e98a2d6e
PP
4324 &entry_node->u.ctf_expression.right, &freq);
4325 if (ret) {
50f6fce8 4326 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 4327 "Unexpected unary expression for clock class's `freq` attribute.");
e98a2d6e
PP
4328 ret = -EINVAL;
4329 goto error;
4330 }
4331
44c440bc 4332 if (freq == UINT64_C(-1) || freq == 0) {
50f6fce8 4333 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
239744fc
PP
4334 "Invalid clock class frequency: freq=%" PRIu64,
4335 freq);
4336 ret = -EINVAL;
4337 goto error;
4338 }
4339
0f2d58c9 4340 clock->frequency = freq;
e98a2d6e 4341 _SET(set, _CLOCK_FREQ_SET);
2242b43d 4342 } else if (strcmp(left, "precision") == 0) {
e98a2d6e
PP
4343 uint64_t precision;
4344
4345 if (_IS_SET(set, _CLOCK_PRECISION_SET)) {
50f6fce8 4346 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "precision",
28973adf 4347 "clock class");
e98a2d6e
PP
4348 ret = -EPERM;
4349 goto error;
4350 }
4351
0746848c 4352 ret = get_unary_unsigned(ctx,
e98a2d6e
PP
4353 &entry_node->u.ctf_expression.right, &precision);
4354 if (ret) {
50f6fce8 4355 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 4356 "Unexpected unary expression for clock class's `precision` attribute.");
e98a2d6e
PP
4357 ret = -EINVAL;
4358 goto error;
4359 }
4360
0f2d58c9 4361 clock->precision = precision;
e98a2d6e 4362 _SET(set, _CLOCK_PRECISION_SET);
2242b43d 4363 } else if (strcmp(left, "offset_s") == 0) {
e98a2d6e 4364 if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) {
50f6fce8 4365 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "offset_s",
28973adf 4366 "clock class");
e98a2d6e
PP
4367 ret = -EPERM;
4368 goto error;
4369 }
4370
fb4ac437 4371 ret = get_unary_signed(
44c440bc 4372 &entry_node->u.ctf_expression.right, offset_seconds);
e98a2d6e 4373 if (ret) {
50f6fce8 4374 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 4375 "Unexpected unary expression for clock class's `offset_s` attribute.");
e98a2d6e
PP
4376 ret = -EINVAL;
4377 goto error;
4378 }
4379
e98a2d6e 4380 _SET(set, _CLOCK_OFFSET_S_SET);
2242b43d 4381 } else if (strcmp(left, "offset") == 0) {
e98a2d6e 4382 if (_IS_SET(set, _CLOCK_OFFSET_SET)) {
50f6fce8 4383 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "offset", "clock class");
e98a2d6e
PP
4384 ret = -EPERM;
4385 goto error;
4386 }
4387
0746848c 4388 ret = get_unary_unsigned(ctx,
44c440bc 4389 &entry_node->u.ctf_expression.right, offset_cycles);
e98a2d6e 4390 if (ret) {
50f6fce8 4391 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 4392 "Unexpected unary expression for clock class's `offset` attribute.");
e98a2d6e
PP
4393 ret = -EINVAL;
4394 goto error;
4395 }
4396
e98a2d6e 4397 _SET(set, _CLOCK_OFFSET_SET);
2242b43d 4398 } else if (strcmp(left, "absolute") == 0) {
e98a2d6e
PP
4399 struct ctf_node *right;
4400
4401 if (_IS_SET(set, _CLOCK_ABSOLUTE_SET)) {
50f6fce8 4402 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "absolute",
28973adf 4403 "clock class");
e98a2d6e
PP
4404 ret = -EPERM;
4405 goto error;
4406 }
4407
4408 right = _BT_LIST_FIRST_ENTRY(
4409 &entry_node->u.ctf_expression.right,
4410 struct ctf_node, siblings);
0746848c 4411 ret = get_boolean(ctx, right);
e98a2d6e 4412 if (ret < 0) {
50f6fce8 4413 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf 4414 "Unexpected unary expression for clock class's `absolute` attribute.");
e98a2d6e
PP
4415 ret = -EINVAL;
4416 goto error;
4417 }
4418
0f2d58c9 4419 clock->is_absolute = ret;
e98a2d6e
PP
4420 _SET(set, _CLOCK_ABSOLUTE_SET);
4421 } else {
f7b785ac 4422 _BT_COMP_LOGW_NODE(entry_node,
28973adf 4423 "Unknown attribute in clock class: attr-name=\"%s\"",
e98a2d6e
PP
4424 left);
4425 }
4426
4427 g_free(left);
4428 left = NULL;
e98a2d6e
PP
4429 return 0;
4430
4431error:
4432 g_free(left);
e98a2d6e
PP
4433 return ret;
4434}
4435
44c440bc
PP
4436static inline
4437uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns)
92540773 4438{
44c440bc 4439 uint64_t cycles;
92540773
JD
4440
4441 /* 1GHz */
44c440bc 4442 if (frequency == UINT64_C(1000000000)) {
92540773
JD
4443 cycles = ns;
4444 } else {
4445 cycles = (uint64_t) (((double) ns * (double) frequency) / 1e9);
4446 }
4447
4448 return cycles;
4449}
4450
4451static
44c440bc
PP
4452void calibrate_clock_class_offsets(int64_t *offset_seconds,
4453 uint64_t *offset_cycles, uint64_t freq)
4454{
4455 if (*offset_cycles >= freq) {
4456 const uint64_t s_in_offset_cycles = *offset_cycles / freq;
4457
4458 *offset_seconds += (int64_t) s_in_offset_cycles;
4459 *offset_cycles -= (s_in_offset_cycles * freq);
4460 }
4461}
4462
c0aa240b 4463static
cf81cdae 4464void apply_clock_class_is_absolute(struct ctf_visitor_generate_ir *ctx,
c0aa240b
FD
4465 struct ctf_clock_class *clock)
4466{
4467 if (ctx->decoder_config.force_clock_class_origin_unix_epoch) {
4468 clock->is_absolute = true;
4469 }
4470
4471 return;
4472}
4473
44c440bc 4474static
cf81cdae 4475void apply_clock_class_offset(struct ctf_visitor_generate_ir *ctx,
0f2d58c9 4476 struct ctf_clock_class *clock)
92540773 4477{
92540773 4478 uint64_t freq;
44c440bc
PP
4479 int64_t offset_s_to_apply = ctx->decoder_config.clock_class_offset_s;
4480 uint64_t offset_ns_to_apply;
4481 int64_t cur_offset_s;
4482 uint64_t cur_offset_cycles;
92540773 4483
44c440bc
PP
4484 if (ctx->decoder_config.clock_class_offset_s == 0 &&
4485 ctx->decoder_config.clock_class_offset_ns == 0) {
92540773
JD
4486 goto end;
4487 }
4488
44c440bc
PP
4489 /* Transfer nanoseconds to seconds as much as possible */
4490 if (ctx->decoder_config.clock_class_offset_ns < 0) {
4491 const int64_t abs_ns = -ctx->decoder_config.clock_class_offset_ns;
4492 const int64_t abs_extra_s = abs_ns / INT64_C(1000000000) + 1;
4493 const int64_t extra_s = -abs_extra_s;
4494 const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
4495 (extra_s * INT64_C(1000000000));
4496
4497 BT_ASSERT(offset_ns > 0);
4498 offset_ns_to_apply = (uint64_t) offset_ns;
4499 offset_s_to_apply += extra_s;
4500 } else {
4501 const int64_t extra_s = ctx->decoder_config.clock_class_offset_ns /
4502 INT64_C(1000000000);
4503 const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
4504 (extra_s * INT64_C(1000000000));
4505
4506 BT_ASSERT(offset_ns >= 0);
4507 offset_ns_to_apply = (uint64_t) offset_ns;
4508 offset_s_to_apply += extra_s;
92540773
JD
4509 }
4510
0f2d58c9
PP
4511 freq = clock->frequency;
4512 cur_offset_s = clock->offset_seconds;
4513 cur_offset_cycles = clock->offset_cycles;
44c440bc
PP
4514
4515 /* Apply offsets */
4516 cur_offset_s += offset_s_to_apply;
4517 cur_offset_cycles += cycles_from_ns(freq, offset_ns_to_apply);
4518
4519 /*
4520 * Recalibrate offsets because the part in cycles can be greater
4521 * than the frequency at this point.
4522 */
4523 calibrate_clock_class_offsets(&cur_offset_s, &cur_offset_cycles, freq);
4524
4525 /* Set final offsets */
0f2d58c9
PP
4526 clock->offset_seconds = cur_offset_s;
4527 clock->offset_cycles = cur_offset_cycles;
92540773
JD
4528
4529end:
44c440bc 4530 return;
92540773
JD
4531}
4532
4533static
cf81cdae 4534int visit_clock_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *clock_node)
e98a2d6e
PP
4535{
4536 int ret = 0;
4537 int set = 0;
0f2d58c9 4538 struct ctf_clock_class *clock;
e98a2d6e
PP
4539 struct ctf_node *entry_node;
4540 struct bt_list_head *decl_list = &clock_node->u.clock.declaration_list;
f4421ff3 4541 const char *clock_class_name;
44c440bc
PP
4542 int64_t offset_seconds = 0;
4543 uint64_t offset_cycles = 0;
4544 uint64_t freq;
e98a2d6e
PP
4545
4546 if (clock_node->visited) {
4547 return 0;
4548 }
4549
4550 clock_node->visited = TRUE;
f3534905
PP
4551
4552 /* CTF 1.8's default frequency for a clock class is 1 GHz */
0f2d58c9 4553 clock = ctf_clock_class_create();
e98a2d6e 4554 if (!clock) {
50f6fce8 4555 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node,
28973adf 4556 "Cannot create default clock class.");
e98a2d6e 4557 ret = -ENOMEM;
44c440bc
PP
4558 goto end;
4559 }
4560
e98a2d6e 4561 bt_list_for_each_entry(entry_node, decl_list, siblings) {
44c440bc
PP
4562 ret = visit_clock_decl_entry(ctx, entry_node, clock, &set,
4563 &offset_seconds, &offset_cycles);
e98a2d6e 4564 if (ret) {
50f6fce8 4565 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
28973adf
PP
4566 "Cannot visit clock class's entry: ret=%d",
4567 ret);
44c440bc 4568 goto end;
e98a2d6e
PP
4569 }
4570 }
4571
4572 if (!_IS_SET(&set, _CLOCK_NAME_SET)) {
50f6fce8 4573 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node,
28973adf 4574 "Missing `name` attribute in clock class.");
e98a2d6e 4575 ret = -EPERM;
44c440bc 4576 goto end;
e98a2d6e
PP
4577 }
4578
0f2d58c9 4579 clock_class_name = clock->name->str;
f6ccaed9 4580 BT_ASSERT(clock_class_name);
f4421ff3
PP
4581 if (ctx->is_lttng && strcmp(clock_class_name, "monotonic") == 0) {
4582 /*
4583 * Old versions of LTTng forgot to set its clock class
4584 * as absolute, even if it is. This is important because
d6e69534 4585 * it's a condition to be able to sort messages
f4421ff3
PP
4586 * from different sources.
4587 */
0f2d58c9 4588 clock->is_absolute = true;
e98a2d6e
PP
4589 }
4590
44c440bc
PP
4591 /*
4592 * Adjust offsets so that the part in cycles is less than the
4593 * frequency (move to the part in seconds).
4594 */
0f2d58c9 4595 freq = clock->frequency;
44c440bc 4596 calibrate_clock_class_offsets(&offset_seconds, &offset_cycles, freq);
0f2d58c9
PP
4597 BT_ASSERT(offset_cycles < clock->frequency);
4598 clock->offset_seconds = offset_seconds;
4599 clock->offset_cycles = offset_cycles;
44c440bc 4600 apply_clock_class_offset(ctx, clock);
c0aa240b 4601 apply_clock_class_is_absolute(ctx, clock);
398454ed 4602 g_ptr_array_add(ctx->ctf_tc->clock_classes, clock);
0f2d58c9 4603 clock = NULL;
e98a2d6e 4604
44c440bc 4605end:
0f2d58c9
PP
4606 if (clock) {
4607 ctf_clock_class_destroy(clock);
4608 }
4609
e98a2d6e
PP
4610 return ret;
4611}
4612
4613static
cf81cdae 4614int visit_root_decl(struct ctf_visitor_generate_ir *ctx, struct ctf_node *root_decl_node)
e98a2d6e
PP
4615{
4616 int ret = 0;
4617
4618 if (root_decl_node->visited) {
4619 goto end;
4620 }
4621
4622 root_decl_node->visited = TRUE;
4623
4624 switch (root_decl_node->type) {
4625 case NODE_TYPEDEF:
5cd6d0e5
PP
4626 ret = visit_field_class_def(ctx,
4627 root_decl_node->u.field_class_def.field_class_specifier_list,
4628 &root_decl_node->u.field_class_def.field_class_declarators);
e98a2d6e 4629 if (ret) {
50f6fce8 4630 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node,
5cd6d0e5 4631 "Cannot add field class found in root scope.");
e98a2d6e
PP
4632 goto end;
4633 }
4634 break;
4635 case NODE_TYPEALIAS:
5cd6d0e5
PP
4636 ret = visit_field_class_alias(ctx, root_decl_node->u.field_class_alias.target,
4637 root_decl_node->u.field_class_alias.alias);
e98a2d6e 4638 if (ret) {
50f6fce8 4639 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node,
5cd6d0e5 4640 "Cannot add field class alias found in root scope.");
e98a2d6e
PP
4641 goto end;
4642 }
4643 break;
4644 case NODE_TYPE_SPECIFIER_LIST:
4645 {
5cd6d0e5 4646 struct ctf_field_class *decl = NULL;
e98a2d6e
PP
4647
4648 /*
5cd6d0e5 4649 * Just add the field class specifier to the root
e98a2d6e
PP
4650 * declaration scope. Put local reference.
4651 */
5cd6d0e5 4652 ret = visit_field_class_specifier_list(ctx, root_decl_node, &decl);
e98a2d6e 4653 if (ret) {
50f6fce8 4654 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node,
5cd6d0e5 4655 "Cannot visit root scope's field class: "
28973adf 4656 "ret=%d", ret);
f6ccaed9 4657 BT_ASSERT(!decl);
e98a2d6e
PP
4658 goto end;
4659 }
4660
5cd6d0e5 4661 ctf_field_class_destroy(decl);
44c440bc 4662 decl = NULL;
e98a2d6e
PP
4663 break;
4664 }
4665 default:
50f6fce8 4666 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node,
28973adf
PP
4667 "Unexpected node type: node-type=%d",
4668 root_decl_node->type);
e98a2d6e
PP
4669 ret = -EPERM;
4670 goto end;
4671 }
4672
4673end:
4674 return ret;
4675}
4676
1e649dff 4677BT_HIDDEN
55314f2a 4678struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create(
862ca4ed 4679 const struct ctf_metadata_decoder_config *decoder_config)
e98a2d6e 4680{
cf81cdae 4681 struct ctf_visitor_generate_ir *ctx = NULL;
e98a2d6e 4682
1e649dff 4683 /* Create visitor's context */
f7b785ac 4684 ctx = ctx_create(decoder_config);
e98a2d6e 4685 if (!ctx) {
9d2c9974
PP
4686 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, decoder_config->log_level,
4687 decoder_config->self_comp,
4688 "Cannot create visitor's context.");
e98a2d6e
PP
4689 goto error;
4690 }
4691
1e649dff
PP
4692 goto end;
4693
4694error:
4695 ctx_destroy(ctx);
4696 ctx = NULL;
4697
4698end:
cf81cdae 4699 return ctx;
1e649dff
PP
4700}
4701
4702BT_HIDDEN
4703void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir *visitor)
4704{
cf81cdae 4705 ctx_destroy(visitor);
1e649dff
PP
4706}
4707
4708BT_HIDDEN
b19ff26f 4709bt_trace_class *ctf_visitor_generate_ir_get_ir_trace_class(
cf81cdae 4710 struct ctf_visitor_generate_ir *ctx)
1e649dff 4711{
98b15851 4712 BT_ASSERT_DBG(ctx);
41693723
PP
4713
4714 if (ctx->trace_class) {
4715 bt_trace_class_get_ref(ctx->trace_class);
4716 }
4717
862ca4ed 4718 return ctx->trace_class;
1e649dff
PP
4719}
4720
44c440bc
PP
4721BT_HIDDEN
4722struct ctf_trace_class *ctf_visitor_generate_ir_borrow_ctf_trace_class(
cf81cdae 4723 struct ctf_visitor_generate_ir *ctx)
44c440bc 4724{
98b15851
PP
4725 BT_ASSERT_DBG(ctx);
4726 BT_ASSERT_DBG(ctx->ctf_tc);
44c440bc
PP
4727 return ctx->ctf_tc;
4728}
4729
1e649dff 4730BT_HIDDEN
cf81cdae 4731int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *ctx,
1e649dff
PP
4732 struct ctf_node *node)
4733{
4734 int ret = 0;
1e649dff 4735
f7b785ac 4736 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
1e649dff 4737
e98a2d6e
PP
4738 switch (node->type) {
4739 case NODE_ROOT:
4740 {
4741 struct ctf_node *iter;
44c440bc 4742 bool got_trace_decl = false;
e98a2d6e
PP
4743
4744 /*
1e649dff 4745 * The first thing we need is the native byte order of
5cd6d0e5 4746 * the trace block, because early class aliases can have
1e649dff
PP
4747 * a `byte_order` attribute set to `native`. If we don't
4748 * have the native byte order yet, and we don't have any
4749 * trace block yet, then fail with EINCOMPLETE.
e98a2d6e 4750 */
e2bd7d40 4751 if (ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_UNKNOWN) {
1e649dff
PP
4752 bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
4753 if (got_trace_decl) {
50f6fce8 4754 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 4755 "Duplicate trace (`trace` block).");
1e649dff
PP
4756 ret = -1;
4757 goto end;
4758 }
e98a2d6e 4759
1e649dff
PP
4760 ret = set_trace_byte_order(ctx, iter);
4761 if (ret) {
50f6fce8 4762 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 4763 "Cannot set trace's native byte order: "
08da4f77 4764 "ret=%d", ret);
1e649dff
PP
4765 goto end;
4766 }
4767
44c440bc 4768 got_trace_decl = true;
e98a2d6e
PP
4769 }
4770
1e649dff 4771 if (!got_trace_decl) {
f7b785ac 4772 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
1e649dff
PP
4773 ret = -EINCOMPLETE;
4774 goto end;
4775 }
e98a2d6e
PP
4776 }
4777
44c440bc
PP
4778 BT_ASSERT(ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_LITTLE ||
4779 ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_BIG);
f6ccaed9 4780 BT_ASSERT(ctx->current_scope &&
5084732e 4781 !ctx->current_scope->parent_scope);
e98a2d6e 4782
f4421ff3
PP
4783 /* Environment */
4784 bt_list_for_each_entry(iter, &node->u.root.env, siblings) {
4785 ret = visit_env(ctx, iter);
4786 if (ret) {
50f6fce8 4787 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
28973adf 4788 "Cannot visit trace's environment (`env` block) entry: "
08da4f77 4789 "ret=%d", ret);
f4421ff3
PP
4790 goto end;
4791 }
4792 }
4793
f6ccaed9 4794 BT_ASSERT(ctx->current_scope &&
5084732e 4795 !ctx->current_scope->parent_scope);
f4421ff3 4796
e98a2d6e 4797 /*
f4421ff3 4798 * Visit clock blocks.
e98a2d6e
PP
4799 */
4800 bt_list_for_each_entry(iter, &node->u.root.clock, siblings) {
1e649dff 4801 ret = visit_clock_decl(ctx, iter);
e98a2d6e 4802 if (ret) {
50f6fce8 4803 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
28973adf 4804 "Cannot visit clock class: ret=%d",
e98a2d6e 4805 ret);
1e649dff 4806 goto end;
e98a2d6e
PP
4807 }
4808 }
4809
f6ccaed9 4810 BT_ASSERT(ctx->current_scope &&
5084732e 4811 !ctx->current_scope->parent_scope);
1e649dff 4812
e98a2d6e
PP
4813 /*
4814 * Visit root declarations next, as they can be used by any
4815 * following entity.
4816 */
4817 bt_list_for_each_entry(iter, &node->u.root.declaration_list,
4818 siblings) {
4819 ret = visit_root_decl(ctx, iter);
4820 if (ret) {
50f6fce8 4821 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
28973adf 4822 "Cannot visit root entry: ret=%d",
e98a2d6e 4823 ret);
1e649dff 4824 goto end;
e98a2d6e
PP
4825 }
4826 }
4827
f6ccaed9 4828 BT_ASSERT(ctx->current_scope &&
5084732e 4829 !ctx->current_scope->parent_scope);
1e649dff
PP
4830
4831 /* Callsite blocks are not supported */
e98a2d6e 4832 bt_list_for_each_entry(iter, &node->u.root.callsite, siblings) {
f7b785ac 4833 _BT_COMP_LOGW_NODE(iter,
28973adf 4834 "\"callsite\" blocks are not supported as of this version.");
e98a2d6e
PP
4835 }
4836
f6ccaed9 4837 BT_ASSERT(ctx->current_scope &&
5084732e 4838 !ctx->current_scope->parent_scope);
1e649dff 4839
e98a2d6e
PP
4840 /* Trace */
4841 bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
4842 ret = visit_trace_decl(ctx, iter);
4843 if (ret) {
50f6fce8 4844 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
28973adf 4845 "Cannot visit trace (`trace` block): "
08da4f77 4846 "ret=%d", ret);
1e649dff 4847 goto end;
e98a2d6e
PP
4848 }
4849 }
4850
f6ccaed9 4851 BT_ASSERT(ctx->current_scope &&
5084732e 4852 !ctx->current_scope->parent_scope);
1e649dff 4853
e98a2d6e
PP
4854 /* Streams */
4855 bt_list_for_each_entry(iter, &node->u.root.stream, siblings) {
4856 ret = visit_stream_decl(ctx, iter);
4857 if (ret) {
50f6fce8 4858 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
28973adf 4859 "Cannot visit stream class: ret=%d",
08da4f77 4860 ret);
1e649dff 4861 goto end;
e98a2d6e
PP
4862 }
4863 }
4864
f6ccaed9 4865 BT_ASSERT(ctx->current_scope &&
5084732e 4866 !ctx->current_scope->parent_scope);
1e649dff 4867
e98a2d6e
PP
4868 /* Events */
4869 bt_list_for_each_entry(iter, &node->u.root.event, siblings) {
4870 ret = visit_event_decl(ctx, iter);
4871 if (ret) {
50f6fce8 4872 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
28973adf 4873 "Cannot visit event class: ret=%d",
08da4f77 4874 ret);
1e649dff 4875 goto end;
e98a2d6e
PP
4876 }
4877 }
1e649dff 4878
f6ccaed9 4879 BT_ASSERT(ctx->current_scope &&
5084732e 4880 !ctx->current_scope->parent_scope);
e98a2d6e
PP
4881 break;
4882 }
e98a2d6e 4883 default:
50f6fce8 4884 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
28973adf 4885 "Unexpected node type: node-type=%d",
08da4f77 4886 node->type);
e98a2d6e 4887 ret = -EINVAL;
1e649dff 4888 goto end;
e98a2d6e
PP
4889 }
4890
44c440bc 4891 /* Update default clock classes */
0746848c 4892 ret = ctf_trace_class_update_default_clock_classes(ctx->ctf_tc,
f7b785ac 4893 &ctx->log_cfg);
44c440bc
PP
4894 if (ret) {
4895 ret = -EINVAL;
4896 goto end;
4897 }
4898
44c440bc
PP
4899 /* Update trace class meanings */
4900 ret = ctf_trace_class_update_meanings(ctx->ctf_tc);
4901 if (ret) {
4902 ret = -EINVAL;
4903 goto end;
4904 }
4905
afd45274
PP
4906 /* Update stream class configuration */
4907 ret = ctf_trace_class_update_stream_class_config(ctx->ctf_tc);
4908 if (ret) {
4909 ret = -EINVAL;
4910 goto end;
4911 }
4912
44c440bc
PP
4913 /* Update text arrays and sequences */
4914 ret = ctf_trace_class_update_text_array_sequence(ctx->ctf_tc);
4915 if (ret) {
4916 ret = -EINVAL;
4917 goto end;
4918 }
4919
e6938018
PP
4920 /* Update structure/array/sequence alignments */
4921 ret = ctf_trace_class_update_alignments(ctx->ctf_tc);
4922 if (ret) {
4923 ret = -EINVAL;
4924 goto end;
4925 }
4926
44c440bc 4927 /* Resolve sequence lengths and variant tags */
f7b785ac 4928 ret = ctf_trace_class_resolve_field_classes(ctx->ctf_tc, &ctx->log_cfg);
44c440bc
PP
4929 if (ret) {
4930 ret = -EINVAL;
4931 goto end;
4932 }
4933
41693723
PP
4934 if (ctx->trace_class) {
4935 /*
4936 * Update "in IR" for field classes.
4937 *
4938 * If we have no IR trace class, then we'll have no way
4939 * to create IR fields anyway, so we leave all the
4940 * `in_ir` members false.
4941 */
4942 ret = ctf_trace_class_update_in_ir(ctx->ctf_tc);
4943 if (ret) {
4944 ret = -EINVAL;
4945 goto end;
4946 }
44c440bc
PP
4947 }
4948
4949 /* Update saved value indexes */
4950 ret = ctf_trace_class_update_value_storing_indexes(ctx->ctf_tc);
e98a2d6e 4951 if (ret) {
44c440bc
PP
4952 ret = -EINVAL;
4953 goto end;
4954 }
4955
4956 /* Validate what we have so far */
f7b785ac 4957 ret = ctf_trace_class_validate(ctx->ctf_tc, &ctx->log_cfg);
44c440bc
PP
4958 if (ret) {
4959 ret = -EINVAL;
4960 goto end;
4961 }
4962
83ebb7f1
PP
4963 /*
4964 * If there are fields which are not related to the CTF format
4965 * itself in the packet header and in event header field
4966 * classes, warn about it because they are never translated.
4967 */
0746848c 4968 ctf_trace_class_warn_meaningless_header_fields(ctx->ctf_tc,
f7b785ac 4969 &ctx->log_cfg);
83ebb7f1 4970
41693723
PP
4971 if (ctx->trace_class) {
4972 /* Copy new CTF metadata -> new IR metadata */
f7b785ac 4973 ret = ctf_trace_class_translate(ctx->log_cfg.self_comp,
7fcdb0a9 4974 ctx->trace_class, ctx->ctf_tc);
41693723
PP
4975 if (ret) {
4976 ret = -EINVAL;
4977 goto end;
4978 }
e98a2d6e
PP
4979 }
4980
1e649dff 4981end:
e98a2d6e
PP
4982 return ret;
4983}
This page took 0.376119 seconds and 4 git commands to generate.