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