1458cc72857dc2eb4378603d0fe6c180e4108537
[lttng-tools.git] / src / lib / lttng-ctl / filter / filter-visitor-generate-ir.c
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>
29 #include "filter-ast.h"
30 #include "filter-parser.h"
31 #include "filter-ir.h"
32
33 #include <common/macros.h>
34
35 static
36 struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx,
37 struct filter_node *node, enum ir_side side);
38
39 static
40 struct 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");
51 free(op);
52 return NULL;
53 case IR_DATA_STRING:
54 fprintf(stderr, "[error] String cannot be root data type\n");
55 free(op);
56 return NULL;
57 case IR_DATA_NUMERIC:
58 case IR_DATA_FIELD_REF:
59 case IR_DATA_GET_CONTEXT_REF:
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
71 static
72 struct 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
91 static
92 struct 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
108 static
109 struct 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
124 static
125 struct 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
144 static
145 struct 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
164 static
165 struct 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
187 error:
188 free(op);
189 return NULL;
190 }
191
192 /*
193 * unary + is pretty much useless.
194 */
195 static
196 struct 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
202 static
203 struct 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
209 static
210 struct 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
217 static
218 struct 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 */
248 if (left->data_type != IR_DATA_FIELD_REF
249 && left->data_type != IR_DATA_GET_CONTEXT_REF)
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
269 error:
270 free(op);
271 return NULL;
272 }
273
274 static
275 struct 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
281 static
282 struct 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
288 static
289 struct 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
295 static
296 struct 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
302 static
303 struct 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
309 static
310 struct 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
316 static
317 struct 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
323 static
324 struct 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
330 static
331 struct 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
337 static
338 struct 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
345 static
346 struct 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
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) &&
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
381 error:
382 free(op);
383 return NULL;
384 }
385
386 static
387 struct 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
393 static
394 struct 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
400 static
401 struct 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
407 static
408 struct 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
414 static
415 struct 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
421 static
422 struct 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
428 static
429 struct 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
462 error:
463 free(op);
464 return NULL;
465 }
466
467 static
468 struct 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
474 static
475 struct 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
481 static
482 void 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;
500 case IR_DATA_FIELD_REF: /* fall-through */
501 case IR_DATA_GET_CONTEXT_REF:
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
523 static
524 struct 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);
538 case AST_EXP_FLOAT_CONSTANT:
539 return make_op_load_float(node->u.expression.u.float_constant,
540 side);
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);
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 }
582 case AST_EXP_NESTED:
583 return generate_ir_recursive(ctx, node->u.expression.u.child,
584 side);
585 }
586 }
587
588 static
589 struct 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
706 error_not_supported:
707 fprintf(stderr, "[error] %s: binary operation '%s' not supported\n",
708 __func__, op_str);
709 return NULL;
710 }
711
712 static
713 struct ir_op *make_unary_op(struct filter_parser_ctx *ctx,
714 struct filter_node *node, enum ir_side side)
715 {
716 const char *op_str = "?";
717
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 }
769 case AST_UNARY_BIN_NOT:
770 {
771 op_str = "~";
772 goto error_not_supported;
773 }
774 }
775
776 error_not_supported:
777 fprintf(stderr, "[error] %s: unary operation '%s' not supported\n",
778 __func__, op_str);
779 return NULL;
780 }
781
782 static
783 struct 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
817 LTTNG_HIDDEN
818 void filter_ir_free(struct filter_parser_ctx *ctx)
819 {
820 filter_free_ir_recursive(ctx->ir_root);
821 ctx->ir_root = NULL;
822 }
823
824 LTTNG_HIDDEN
825 int 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.044776 seconds and 3 git commands to generate.