Implement support for brackets in filter expressions
[lttng-tools.git] / src / lib / lttng-ctl / filter / filter-visitor-generate-ir.c
CommitLineData
953192ba
MD
1/*
2 * filter-visitor-generate-ir.c
3 *
4 * LTTng filter generate intermediate representation
5 *
6 * Copyright 2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License, version 2.1 only,
10 * as published by the Free Software Foundation.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdio.h>
23#include <unistd.h>
24#include <string.h>
25#include <stdlib.h>
26#include <assert.h>
27#include <errno.h>
28#include <inttypes.h>
953192ba 29#include "filter-ast.h"
95b9bd90 30#include "filter-parser.h"
953192ba
MD
31#include "filter-ir.h"
32
a187da1a 33#include <common/macros.h>
9f449915 34#include <common/string-utils/string-utils.h>
a187da1a 35
953192ba
MD
36static
37struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx,
38 struct filter_node *node, enum ir_side side);
39
40static
41struct ir_op *make_op_root(struct ir_op *child, enum ir_side side)
42{
43 struct ir_op *op;
44
45 op = calloc(sizeof(struct ir_op), 1);
46 if (!op)
47 return NULL;
48 switch (child->data_type) {
49 case IR_DATA_UNKNOWN:
50 default:
51 fprintf(stderr, "[error] Unknown root child data type\n");
7d8868f9 52 free(op);
953192ba
MD
53 return NULL;
54 case IR_DATA_STRING:
55 fprintf(stderr, "[error] String cannot be root data type\n");
7d8868f9 56 free(op);
953192ba
MD
57 return NULL;
58 case IR_DATA_NUMERIC:
59 case IR_DATA_FIELD_REF:
586dc72f 60 case IR_DATA_GET_CONTEXT_REF:
953192ba
MD
61 /* ok */
62 break;
63 }
64 op->op = IR_OP_ROOT;
65 op->side = side;
66 op->data_type = child->data_type;
67 op->signedness = child->signedness;
68 op->u.root.child = child;
69 return op;
70}
71
9f449915
PP
72static
73enum ir_load_string_type get_literal_string_type(const char *string)
74{
75 assert(string);
76
77 if (strutils_is_star_glob_pattern(string)) {
78 if (strutils_is_star_at_the_end_only_glob_pattern(string)) {
79 return IR_LOAD_STRING_TYPE_GLOB_STAR_END;
80 }
81
82 return IR_LOAD_STRING_TYPE_GLOB_STAR;
83 }
84
85 return IR_LOAD_STRING_TYPE_PLAIN;
86}
87
953192ba
MD
88static
89struct ir_op *make_op_load_string(char *string, enum ir_side side)
90{
91 struct ir_op *op;
92
93 op = calloc(sizeof(struct ir_op), 1);
94 if (!op)
95 return NULL;
96 op->op = IR_OP_LOAD;
97 op->data_type = IR_DATA_STRING;
98 op->signedness = IR_SIGN_UNKNOWN;
99 op->side = side;
9f449915
PP
100 op->u.load.u.string.type = get_literal_string_type(string);
101 op->u.load.u.string.value = strdup(string);
102 if (!op->u.load.u.string.value) {
953192ba
MD
103 free(op);
104 return NULL;
105 }
106 return op;
107}
108
109static
110struct ir_op *make_op_load_numeric(int64_t v, enum ir_side side)
111{
112 struct ir_op *op;
113
114 op = calloc(sizeof(struct ir_op), 1);
115 if (!op)
116 return NULL;
117 op->op = IR_OP_LOAD;
118 op->data_type = IR_DATA_NUMERIC;
119 /* TODO: for now, all numeric values are signed */
120 op->signedness = IR_SIGNED;
121 op->side = side;
122 op->u.load.u.num = v;
123 return op;
124}
125
e90d8561
MD
126static
127struct ir_op *make_op_load_float(double v, enum ir_side side)
128{
129 struct ir_op *op;
130
131 op = calloc(sizeof(struct ir_op), 1);
132 if (!op)
133 return NULL;
134 op->op = IR_OP_LOAD;
135 op->data_type = IR_DATA_FLOAT;
136 op->signedness = IR_SIGN_UNKNOWN;
137 op->side = side;
138 op->u.load.u.flt = v;
139 return op;
140}
141
953192ba 142static
661dfdd1
MD
143struct ir_op *make_op_load_field_ref(char *string,
144 enum ir_side side)
953192ba
MD
145{
146 struct ir_op *op;
147
148 op = calloc(sizeof(struct ir_op), 1);
149 if (!op)
150 return NULL;
151 op->op = IR_OP_LOAD;
152 op->data_type = IR_DATA_FIELD_REF;
153 op->signedness = IR_SIGN_DYN;
154 op->side = side;
155 op->u.load.u.ref = strdup(string);
156 if (!op->u.load.u.ref) {
661dfdd1
MD
157 goto error;
158 }
159 return op;
160
161error:
162 free(op);
163 return NULL;
164}
165
166static
167struct ir_op *make_op_load_field_ref_index(char *string,
168 struct filter_node *next,
169 enum ir_side side)
170{
171 struct ir_op *op;
172
173 op = calloc(sizeof(struct ir_op), 1);
174 if (!op)
953192ba 175 return NULL;
661dfdd1
MD
176 op->op = IR_OP_LOAD;
177 op->data_type = IR_DATA_FIELD_REF_INDEX;
178 op->signedness = IR_SIGN_DYN;
179 op->side = side;
180 op->u.load.u.ref_index.symbol = strdup(string);
181 if (!op->u.load.u.ref_index.symbol) {
182 goto error;
183 }
184 /* Only positive integer literals accepted as index. */
185 if (next->type == NODE_UNARY_OP) {
186 fprintf(stderr, "[error] Unexpected unary operator as index\n");
187 goto error;
188 }
189 if (next->type != NODE_EXPRESSION) {
190 fprintf(stderr, "[error] Expecting expression as index\n");
191 goto error;
192 }
193 if (next->u.expression.type != AST_EXP_CONSTANT) {
194 fprintf(stderr, "[error] Expecting constant index\n");
195 goto error;
196 }
197 if (next->u.expression.u.constant < 0) {
198 fprintf(stderr, "[error] Expecting positive constant index\n");
199 goto error;
953192ba 200 }
661dfdd1 201 op->u.load.u.ref_index.index = next->u.expression.u.constant;
953192ba 202 return op;
661dfdd1
MD
203
204error:
205 free(op);
206 return NULL;
953192ba
MD
207}
208
586dc72f 209static
661dfdd1
MD
210struct ir_op *make_op_load_get_context_ref(char *string,
211 enum ir_side side)
586dc72f
MD
212{
213 struct ir_op *op;
214
215 op = calloc(sizeof(struct ir_op), 1);
216 if (!op)
217 return NULL;
218 op->op = IR_OP_LOAD;
219 op->data_type = IR_DATA_GET_CONTEXT_REF;
220 op->signedness = IR_SIGN_DYN;
221 op->side = side;
222 op->u.load.u.ref = strdup(string);
223 if (!op->u.load.u.ref) {
661dfdd1
MD
224 goto error;
225 }
226 return op;
227
228error:
229 free(op);
230 return NULL;
231}
232
233static
234struct ir_op *make_op_load_get_context_ref_index(char *string,
235 struct filter_node *next,
236 enum ir_side side)
237{
238 struct ir_op *op;
239
240 op = calloc(sizeof(struct ir_op), 1);
241 if (!op)
586dc72f 242 return NULL;
661dfdd1
MD
243 op->op = IR_OP_LOAD;
244 op->data_type = IR_DATA_GET_CONTEXT_REF_INDEX;
245 op->signedness = IR_SIGN_DYN;
246 op->side = side;
247 op->u.load.u.ref_index.symbol = strdup(string);
248 if (!op->u.load.u.ref_index.symbol) {
249 goto error;
250 }
251 /* Only positive integer literals accepted as offset. */
252 if (next->type == NODE_UNARY_OP) {
253 fprintf(stderr, "[error] Unexpected unary operator as index\n");
254 goto error;
255 }
256 if (next->type != NODE_EXPRESSION) {
257 fprintf(stderr, "[error] Expecting expression as index\n");
258 goto error;
586dc72f 259 }
661dfdd1
MD
260 if (next->u.expression.type != AST_EXP_CONSTANT) {
261 fprintf(stderr, "[error] Expecting constant index\n");
262 goto error;
263 }
264 if (next->u.expression.u.constant < 0) {
265 fprintf(stderr, "[error] Expecting positive constant index\n");
266 goto error;
267 }
268 op->u.load.u.ref_index.index = next->u.expression.u.constant;
586dc72f 269 return op;
661dfdd1
MD
270
271error:
272 free(op);
273 return NULL;
586dc72f
MD
274}
275
953192ba
MD
276static
277struct ir_op *make_op_unary(enum unary_op_type unary_op_type,
278 const char *op_str, enum ir_op_signedness signedness,
279 struct ir_op *child, enum ir_side side)
280{
281 struct ir_op *op = NULL;
282
283 if (child->data_type == IR_DATA_STRING) {
284 fprintf(stderr, "[error] unary operation '%s' not allowed on string literal\n", op_str);
285 goto error;
286 }
287
288 op = calloc(sizeof(struct ir_op), 1);
289 if (!op)
290 return NULL;
291 op->op = IR_OP_UNARY;
292 op->data_type = child->data_type;
293 op->signedness = signedness;
294 op->side = side;
295 op->u.unary.type = unary_op_type;
296 op->u.unary.child = child;
297 return op;
298
299error:
300 free(op);
301 return NULL;
302}
303
304/*
305 * unary + is pretty much useless.
306 */
307static
308struct ir_op *make_op_unary_plus(struct ir_op *child, enum ir_side side)
309{
310 return make_op_unary(AST_UNARY_PLUS, "+", child->signedness,
311 child, side);
312}
313
314static
315struct ir_op *make_op_unary_minus(struct ir_op *child, enum ir_side side)
316{
317 return make_op_unary(AST_UNARY_MINUS, "-", child->signedness,
318 child, side);
319}
320
321static
322struct ir_op *make_op_unary_not(struct ir_op *child, enum ir_side side)
323{
324 return make_op_unary(AST_UNARY_NOT, "!", child->signedness,
325 child, side);
326}
327
953192ba
MD
328static
329struct ir_op *make_op_binary_compare(enum op_type bin_op_type,
330 const char *op_str, struct ir_op *left, struct ir_op *right,
331 enum ir_side side)
332{
333 struct ir_op *op = NULL;
334
335 if (left->data_type == IR_DATA_UNKNOWN
336 || right->data_type == IR_DATA_UNKNOWN) {
337 fprintf(stderr, "[error] binary operation '%s' has unknown operand type\n", op_str);
338 goto error;
339
340 }
341 if ((left->data_type == IR_DATA_STRING
e90d8561
MD
342 && (right->data_type == IR_DATA_NUMERIC || right->data_type == IR_DATA_FLOAT))
343 || ((left->data_type == IR_DATA_NUMERIC || left->data_type == IR_DATA_FLOAT) &&
953192ba
MD
344 right->data_type == IR_DATA_STRING)) {
345 fprintf(stderr, "[error] binary operation '%s' operand type mismatch\n", op_str);
346 goto error;
347 }
348
349 op = calloc(sizeof(struct ir_op), 1);
350 if (!op)
351 return NULL;
352 op->op = IR_OP_BINARY;
353 op->u.binary.type = bin_op_type;
354 op->u.binary.left = left;
355 op->u.binary.right = right;
356
357 /* we return a boolean, represented as signed numeric */
358 op->data_type = IR_DATA_NUMERIC;
359 op->signedness = IR_SIGNED;
360 op->side = side;
361
362 return op;
363
364error:
365 free(op);
366 return NULL;
367}
368
369static
370struct ir_op *make_op_binary_eq(struct ir_op *left, struct ir_op *right,
371 enum ir_side side)
372{
373 return make_op_binary_compare(AST_OP_EQ, "==", left, right, side);
374}
375
376static
377struct ir_op *make_op_binary_ne(struct ir_op *left, struct ir_op *right,
378 enum ir_side side)
379{
380 return make_op_binary_compare(AST_OP_NE, "!=", left, right, side);
381}
382
383static
384struct ir_op *make_op_binary_gt(struct ir_op *left, struct ir_op *right,
385 enum ir_side side)
386{
387 return make_op_binary_compare(AST_OP_GT, ">", left, right, side);
388}
389
390static
391struct ir_op *make_op_binary_lt(struct ir_op *left, struct ir_op *right,
392 enum ir_side side)
393{
394 return make_op_binary_compare(AST_OP_LT, "<", left, right, side);
395}
396
397static
398struct ir_op *make_op_binary_ge(struct ir_op *left, struct ir_op *right,
399 enum ir_side side)
400{
401 return make_op_binary_compare(AST_OP_GE, ">=", left, right, side);
402}
403
404static
405struct ir_op *make_op_binary_le(struct ir_op *left, struct ir_op *right,
406 enum ir_side side)
407{
408 return make_op_binary_compare(AST_OP_LE, "<=", left, right, side);
409}
410
411static
412struct ir_op *make_op_binary_logical(enum op_type bin_op_type,
413 const char *op_str, struct ir_op *left, struct ir_op *right,
414 enum ir_side side)
415{
416 struct ir_op *op = NULL;
417
418 if (left->data_type == IR_DATA_UNKNOWN
419 || right->data_type == IR_DATA_UNKNOWN) {
420 fprintf(stderr, "[error] binary operation '%s' has unknown operand type\n", op_str);
421 goto error;
422
423 }
424 if (left->data_type == IR_DATA_STRING
425 || right->data_type == IR_DATA_STRING) {
426 fprintf(stderr, "[error] logical binary operation '%s' cannot have string operand\n", op_str);
427 goto error;
428 }
429
430 op = calloc(sizeof(struct ir_op), 1);
431 if (!op)
432 return NULL;
433 op->op = IR_OP_LOGICAL;
434 op->u.binary.type = bin_op_type;
435 op->u.binary.left = left;
436 op->u.binary.right = right;
437
438 /* we return a boolean, represented as signed numeric */
439 op->data_type = IR_DATA_NUMERIC;
440 op->signedness = IR_SIGNED;
441 op->side = side;
442
443 return op;
444
445error:
446 free(op);
447 return NULL;
448}
449
450static
451struct ir_op *make_op_binary_logical_and(struct ir_op *left, struct ir_op *right,
452 enum ir_side side)
453{
454 return make_op_binary_logical(AST_OP_AND, "&&", left, right, side);
455}
456
457static
458struct ir_op *make_op_binary_logical_or(struct ir_op *left, struct ir_op *right,
459 enum ir_side side)
460{
461 return make_op_binary_logical(AST_OP_OR, "||", left, right, side);
462}
463
464static
465void filter_free_ir_recursive(struct ir_op *op)
466{
467 if (!op)
468 return;
469 switch (op->op) {
470 case IR_OP_UNKNOWN:
471 default:
472 fprintf(stderr, "[error] Unknown op type in %s\n",
473 __func__);
474 break;
475 case IR_OP_ROOT:
476 filter_free_ir_recursive(op->u.root.child);
477 break;
478 case IR_OP_LOAD:
479 switch (op->data_type) {
480 case IR_DATA_STRING:
9f449915 481 free(op->u.load.u.string.value);
953192ba 482 break;
586dc72f
MD
483 case IR_DATA_FIELD_REF: /* fall-through */
484 case IR_DATA_GET_CONTEXT_REF:
953192ba
MD
485 free(op->u.load.u.ref);
486 break;
661dfdd1
MD
487 case IR_DATA_FIELD_REF_INDEX: /* fall-through */
488 case IR_DATA_GET_CONTEXT_REF_INDEX:
489 free(op->u.load.u.ref_index.symbol);
490 break;
953192ba
MD
491 default:
492 break;
493 }
494 break;
495 case IR_OP_UNARY:
496 filter_free_ir_recursive(op->u.unary.child);
497 break;
498 case IR_OP_BINARY:
499 filter_free_ir_recursive(op->u.binary.left);
500 filter_free_ir_recursive(op->u.binary.right);
501 break;
502 case IR_OP_LOGICAL:
503 filter_free_ir_recursive(op->u.logical.left);
504 filter_free_ir_recursive(op->u.logical.right);
505 break;
506 }
507 free(op);
508}
509
510static
511struct ir_op *make_expression(struct filter_parser_ctx *ctx,
512 struct filter_node *node, enum ir_side side)
513{
514 switch (node->u.expression.type) {
515 case AST_EXP_UNKNOWN:
516 default:
517 fprintf(stderr, "[error] %s: unknown expression type\n", __func__);
518 return NULL;
519
520 case AST_EXP_STRING:
521 return make_op_load_string(node->u.expression.u.string, side);
522 case AST_EXP_CONSTANT:
523 return make_op_load_numeric(node->u.expression.u.constant,
524 side);
e90d8561
MD
525 case AST_EXP_FLOAT_CONSTANT:
526 return make_op_load_float(node->u.expression.u.float_constant,
527 side);
953192ba 528 case AST_EXP_IDENTIFIER:
661dfdd1
MD
529 switch (node->u.expression.pre_op) {
530 case AST_LINK_UNKNOWN:
531 return make_op_load_field_ref(node->u.expression.u.identifier,
532 side);
533 case AST_LINK_BRACKET:
534 return make_op_load_field_ref_index(node->u.expression.u.identifier,
535 node->u.expression.next,
536 side);
537 default:
953192ba
MD
538 fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__);
539 return NULL;
540 }
586dc72f
MD
541 case AST_EXP_GLOBAL_IDENTIFIER:
542 {
a1f68b22 543 const char *name;
586dc72f 544
a1f68b22
MD
545 /*
546 * We currently only support $ctx (context) and $app
547 * identifiers.
548 */
586dc72f 549 if (strncmp(node->u.expression.u.identifier,
a1f68b22
MD
550 "$ctx.", strlen("$ctx.")) != 0
551 && strncmp(node->u.expression.u.identifier,
552 "$app.", strlen("$app.")) != 0) {
553 fprintf(stderr, "[error] %s: \"%s\" global identifier is unknown. Only \"$ctx\" and \"$app\" are currently implemented.\n", __func__, node->u.expression.u.identifier);
586dc72f
MD
554 return NULL;
555 }
a1f68b22
MD
556 name = strchr(node->u.expression.u.identifier, '.');
557 if (!name) {
558 fprintf(stderr, "[error] %s: Expecting '.'\n", __func__);
586dc72f
MD
559 return NULL;
560 }
a1f68b22
MD
561 name++; /* Skip . */
562 if (!strlen(name)) {
563 fprintf(stderr, "[error] %s: Expecting a context name, e.g. \'$ctx.name\'.\n", __func__);
586dc72f
MD
564 return NULL;
565 }
661dfdd1
MD
566 switch (node->u.expression.pre_op) {
567 case AST_LINK_UNKNOWN:
568 return make_op_load_get_context_ref(node->u.expression.u.identifier,
586dc72f 569 side);
661dfdd1
MD
570 case AST_LINK_BRACKET:
571 return make_op_load_get_context_ref_index(node->u.expression.u.identifier,
572 node->u.expression.next,
573 side);
574 default:
575 fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__);
576 return NULL;
577 }
578
586dc72f 579 }
953192ba
MD
580 case AST_EXP_NESTED:
581 return generate_ir_recursive(ctx, node->u.expression.u.child,
582 side);
583 }
584}
585
586static
587struct ir_op *make_op(struct filter_parser_ctx *ctx,
588 struct filter_node *node, enum ir_side side)
589{
590 struct ir_op *op = NULL, *lchild, *rchild;
591 const char *op_str = "?";
592
593 switch (node->u.op.type) {
594 case AST_OP_UNKNOWN:
595 default:
596 fprintf(stderr, "[error] %s: unknown binary op type\n", __func__);
597 return NULL;
598
599 /*
600 * Binary operators other than comparators and logical and/or
601 * are not supported. If we ever want to support those, we will
602 * need a stack for the general case rather than just 2
603 * registers (see bytecode).
604 */
605 case AST_OP_MUL:
606 op_str = "*";
607 goto error_not_supported;
608 case AST_OP_DIV:
609 op_str = "/";
610 goto error_not_supported;
611 case AST_OP_MOD:
612 op_str = "%";
613 goto error_not_supported;
614 case AST_OP_PLUS:
615 op_str = "+";
616 goto error_not_supported;
617 case AST_OP_MINUS:
618 op_str = "-";
619 goto error_not_supported;
620 case AST_OP_RSHIFT:
621 op_str = ">>";
622 goto error_not_supported;
623 case AST_OP_LSHIFT:
624 op_str = "<<";
625 goto error_not_supported;
626 case AST_OP_BIN_AND:
627 op_str = "&";
628 goto error_not_supported;
629 case AST_OP_BIN_OR:
630 op_str = "|";
631 goto error_not_supported;
632 case AST_OP_BIN_XOR:
633 op_str = "^";
634 goto error_not_supported;
635
636 case AST_OP_EQ:
637 case AST_OP_NE:
638 case AST_OP_GT:
639 case AST_OP_LT:
640 case AST_OP_GE:
641 case AST_OP_LE:
642 lchild = generate_ir_recursive(ctx, node->u.op.lchild, IR_LEFT);
643 if (!lchild)
644 return NULL;
645 rchild = generate_ir_recursive(ctx, node->u.op.rchild, IR_RIGHT);
646 if (!rchild) {
647 filter_free_ir_recursive(lchild);
648 return NULL;
649 }
650 break;
651
652 case AST_OP_AND:
653 case AST_OP_OR:
654 /*
655 * Both children considered as left, since we need to
656 * populate R0.
657 */
658 lchild = generate_ir_recursive(ctx, node->u.op.lchild, IR_LEFT);
659 if (!lchild)
660 return NULL;
661 rchild = generate_ir_recursive(ctx, node->u.op.rchild, IR_LEFT);
662 if (!rchild) {
663 filter_free_ir_recursive(lchild);
664 return NULL;
665 }
666 break;
667 }
668
669 switch (node->u.op.type) {
670 case AST_OP_AND:
671 op = make_op_binary_logical_and(lchild, rchild, side);
672 break;
673 case AST_OP_OR:
674 op = make_op_binary_logical_or(lchild, rchild, side);
675 break;
676 case AST_OP_EQ:
677 op = make_op_binary_eq(lchild, rchild, side);
678 break;
679 case AST_OP_NE:
680 op = make_op_binary_ne(lchild, rchild, side);
681 break;
682 case AST_OP_GT:
683 op = make_op_binary_gt(lchild, rchild, side);
684 break;
685 case AST_OP_LT:
686 op = make_op_binary_lt(lchild, rchild, side);
687 break;
688 case AST_OP_GE:
689 op = make_op_binary_ge(lchild, rchild, side);
690 break;
691 case AST_OP_LE:
692 op = make_op_binary_le(lchild, rchild, side);
693 break;
694 default:
695 break;
696 }
697
698 if (!op) {
699 filter_free_ir_recursive(rchild);
700 filter_free_ir_recursive(lchild);
701 }
702 return op;
703
704error_not_supported:
705 fprintf(stderr, "[error] %s: binary operation '%s' not supported\n",
706 __func__, op_str);
707 return NULL;
708}
709
710static
711struct ir_op *make_unary_op(struct filter_parser_ctx *ctx,
712 struct filter_node *node, enum ir_side side)
713{
ab78f161
CB
714 const char *op_str = "?";
715
953192ba
MD
716 switch (node->u.unary_op.type) {
717 case AST_UNARY_UNKNOWN:
718 default:
719 fprintf(stderr, "[error] %s: unknown unary op type\n", __func__);
720 return NULL;
721
722 case AST_UNARY_PLUS:
723 {
724 struct ir_op *op, *child;
725
726 child = generate_ir_recursive(ctx, node->u.unary_op.child,
727 side);
728 if (!child)
729 return NULL;
730 op = make_op_unary_plus(child, side);
731 if (!op) {
732 filter_free_ir_recursive(child);
733 return NULL;
734 }
735 return op;
736 }
737 case AST_UNARY_MINUS:
738 {
739 struct ir_op *op, *child;
740
741 child = generate_ir_recursive(ctx, node->u.unary_op.child,
742 side);
743 if (!child)
744 return NULL;
745 op = make_op_unary_minus(child, side);
746 if (!op) {
747 filter_free_ir_recursive(child);
748 return NULL;
749 }
750 return op;
751 }
752 case AST_UNARY_NOT:
753 {
754 struct ir_op *op, *child;
755
756 child = generate_ir_recursive(ctx, node->u.unary_op.child,
757 side);
758 if (!child)
759 return NULL;
760 op = make_op_unary_not(child, side);
761 if (!op) {
762 filter_free_ir_recursive(child);
763 return NULL;
764 }
765 return op;
766 }
ab78f161
CB
767 case AST_UNARY_BIN_NOT:
768 {
769 op_str = "~";
770 goto error_not_supported;
771 }
953192ba 772 }
ab78f161
CB
773
774error_not_supported:
775 fprintf(stderr, "[error] %s: unary operation '%s' not supported\n",
776 __func__, op_str);
777 return NULL;
953192ba
MD
778}
779
780static
781struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx,
782 struct filter_node *node, enum ir_side side)
783{
784 switch (node->type) {
785 case NODE_UNKNOWN:
786 default:
787 fprintf(stderr, "[error] %s: unknown node type\n", __func__);
788 return NULL;
789
790 case NODE_ROOT:
791 {
792 struct ir_op *op, *child;
793
794 child = generate_ir_recursive(ctx, node->u.root.child,
795 side);
796 if (!child)
797 return NULL;
798 op = make_op_root(child, side);
799 if (!op) {
800 filter_free_ir_recursive(child);
801 return NULL;
802 }
803 return op;
804 }
805 case NODE_EXPRESSION:
806 return make_expression(ctx, node, side);
807 case NODE_OP:
808 return make_op(ctx, node, side);
809 case NODE_UNARY_OP:
810 return make_unary_op(ctx, node, side);
811 }
812 return 0;
813}
814
a187da1a 815LTTNG_HIDDEN
953192ba
MD
816void filter_ir_free(struct filter_parser_ctx *ctx)
817{
818 filter_free_ir_recursive(ctx->ir_root);
819 ctx->ir_root = NULL;
820}
821
a187da1a 822LTTNG_HIDDEN
953192ba
MD
823int filter_visitor_ir_generate(struct filter_parser_ctx *ctx)
824{
825 struct ir_op *op;
826
827 op = generate_ir_recursive(ctx, &ctx->ast->root, IR_LEFT);
828 if (!op) {
829 return -EINVAL;
830 }
831 ctx->ir_root = op;
832 return 0;
833}
This page took 0.084273 seconds and 5 git commands to generate.