Filter: index array, sequences, implement bitwise binary operators
[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 #include <common/string-utils/string-utils.h>
35
36 static
37 struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx,
38 struct filter_node *node, enum ir_side side);
39
40 static
41 struct 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");
52 free(op);
53 return NULL;
54 case IR_DATA_STRING:
55 fprintf(stderr, "[error] String cannot be root data type\n");
56 free(op);
57 return NULL;
58 case IR_DATA_NUMERIC:
59 case IR_DATA_FIELD_REF:
60 case IR_DATA_GET_CONTEXT_REF:
61 case IR_DATA_EXPRESSION:
62 /* ok */
63 break;
64 }
65 op->op = IR_OP_ROOT;
66 op->side = side;
67 op->data_type = child->data_type;
68 op->signedness = child->signedness;
69 op->u.root.child = child;
70 return op;
71 }
72
73 static
74 enum ir_load_string_type get_literal_string_type(const char *string)
75 {
76 assert(string);
77
78 if (strutils_is_star_glob_pattern(string)) {
79 if (strutils_is_star_at_the_end_only_glob_pattern(string)) {
80 return IR_LOAD_STRING_TYPE_GLOB_STAR_END;
81 }
82
83 return IR_LOAD_STRING_TYPE_GLOB_STAR;
84 }
85
86 return IR_LOAD_STRING_TYPE_PLAIN;
87 }
88
89 static
90 struct ir_op *make_op_load_string(char *string, enum ir_side side)
91 {
92 struct ir_op *op;
93
94 op = calloc(sizeof(struct ir_op), 1);
95 if (!op)
96 return NULL;
97 op->op = IR_OP_LOAD;
98 op->data_type = IR_DATA_STRING;
99 op->signedness = IR_SIGN_UNKNOWN;
100 op->side = side;
101 op->u.load.u.string.type = get_literal_string_type(string);
102 op->u.load.u.string.value = strdup(string);
103 if (!op->u.load.u.string.value) {
104 free(op);
105 return NULL;
106 }
107 return op;
108 }
109
110 static
111 struct ir_op *make_op_load_numeric(int64_t v, enum ir_side side)
112 {
113 struct ir_op *op;
114
115 op = calloc(sizeof(struct ir_op), 1);
116 if (!op)
117 return NULL;
118 op->op = IR_OP_LOAD;
119 op->data_type = IR_DATA_NUMERIC;
120 /* TODO: for now, all numeric values are signed */
121 op->signedness = IR_SIGNED;
122 op->side = side;
123 op->u.load.u.num = v;
124 return op;
125 }
126
127 static
128 struct ir_op *make_op_load_float(double v, enum ir_side side)
129 {
130 struct ir_op *op;
131
132 op = calloc(sizeof(struct ir_op), 1);
133 if (!op)
134 return NULL;
135 op->op = IR_OP_LOAD;
136 op->data_type = IR_DATA_FLOAT;
137 op->signedness = IR_SIGN_UNKNOWN;
138 op->side = side;
139 op->u.load.u.flt = v;
140 return op;
141 }
142
143 #if 0
144 static
145 struct ir_op *make_op_load_field_ref(char *string,
146 enum ir_side side)
147 {
148 struct ir_op *op;
149
150 op = calloc(sizeof(struct ir_op), 1);
151 if (!op)
152 return NULL;
153 op->op = IR_OP_LOAD;
154 op->data_type = IR_DATA_FIELD_REF;
155 op->signedness = IR_SIGN_DYN;
156 op->side = side;
157 op->u.load.u.ref = strdup(string);
158 if (!op->u.load.u.ref) {
159 goto error;
160 }
161 return op;
162
163 error:
164 free(op);
165 return NULL;
166 }
167 #endif
168
169 static
170 void free_load_expression(struct ir_load_expression *load_expression)
171 {
172 struct ir_load_expression_op *exp_op;
173
174 if (!load_expression)
175 return;
176 exp_op = load_expression->child;
177 for (;;) {
178 struct ir_load_expression_op *prev_exp_op;
179
180 if (!exp_op)
181 break;
182 switch (exp_op->type) {
183 case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT:
184 case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT:
185 case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT:
186 case IR_LOAD_EXPRESSION_GET_INDEX:
187 case IR_LOAD_EXPRESSION_LOAD_FIELD:
188 break;
189 case IR_LOAD_EXPRESSION_GET_SYMBOL:
190 free(exp_op->u.symbol);
191 break;
192 }
193 prev_exp_op = exp_op;
194 exp_op = exp_op->next;
195 free(prev_exp_op);
196 }
197 free(load_expression);
198 }
199
200 /*
201 * Returns the first node of the chain, after initializing the next
202 * pointers.
203 */
204 static
205 struct filter_node *load_expression_get_forward_chain(struct filter_node *node)
206 {
207 struct filter_node *prev_node;
208
209 for (;;) {
210 assert(node->type == NODE_EXPRESSION);
211 prev_node = node;
212 node = node->u.expression.prev;
213 if (!node) {
214 break;
215 }
216 node->u.expression.next = prev_node;
217 }
218 return prev_node;
219 }
220
221 static
222 struct ir_load_expression *create_load_expression(struct filter_node *node)
223 {
224 struct ir_load_expression *load_exp;
225 struct ir_load_expression_op *load_exp_op, *prev_op;
226 char *str;
227
228 /* Get forward chain. */
229 node = load_expression_get_forward_chain(node);
230 if (!node)
231 return NULL;
232 load_exp = calloc(sizeof(struct ir_load_expression), 1);
233 if (!load_exp)
234 return NULL;
235
236 /* Root */
237 load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1);
238 if (!load_exp_op)
239 goto error;
240 load_exp->child = load_exp_op;
241 str = node->u.expression.u.string;
242 if (!strcmp(str, "$ctx")) {
243 load_exp_op->type = IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT;
244 node = node->u.expression.next;
245 if (!node) {
246 fprintf(stderr, "[error] Expecting identifier after \'%s\'\n", str);
247 goto error;
248 }
249 str = node->u.expression.u.string;
250 } else if (!strcmp(str, "$app")) {
251 load_exp_op->type = IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT;
252 node = node->u.expression.next;
253 if (!node) {
254 fprintf(stderr, "[error] Expecting identifier after \'%s\'\n", str);
255 goto error;
256 }
257 str = node->u.expression.u.string;
258 } else if (str[0] == '$') {
259 fprintf(stderr, "[error] Unexpected identifier \'%s\'\n", str);
260 goto error;
261 } else {
262 load_exp_op->type = IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT;
263 }
264
265 for (;;) {
266 struct filter_node *bracket_node;
267
268 prev_op = load_exp_op;
269 load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1);
270 if (!load_exp_op)
271 goto error;
272 prev_op->next = load_exp_op;
273 load_exp_op->type = IR_LOAD_EXPRESSION_GET_SYMBOL;
274 load_exp_op->u.symbol = strdup(str);
275 if (!load_exp_op->u.symbol)
276 goto error;
277
278 /* Explore brackets from current node. */
279 for (bracket_node = node->u.expression.next_bracket;
280 bracket_node != NULL;
281 bracket_node = bracket_node->u.expression.next_bracket) {
282 prev_op = load_exp_op;
283 load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1);
284 if (!load_exp_op)
285 goto error;
286 prev_op->next = load_exp_op;
287 load_exp_op->type = IR_LOAD_EXPRESSION_GET_INDEX;
288 load_exp_op->u.index = bracket_node->u.expression.u.constant;
289 }
290 /* Go to next chain element. */
291 node = node->u.expression.next;
292 if (!node)
293 break;
294 str = node->u.expression.u.string;
295 }
296 /* Add final load field */
297 prev_op = load_exp_op;
298 load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1);
299 if (!load_exp_op)
300 goto error;
301 prev_op->next = load_exp_op;
302 load_exp_op->type = IR_LOAD_EXPRESSION_LOAD_FIELD;
303 return load_exp;
304
305 error:
306 free_load_expression(load_exp);
307 return NULL;
308 }
309
310 static
311 struct ir_op *make_op_load_expression(struct filter_node *node,
312 enum ir_side side)
313 {
314 struct ir_op *op;
315
316 op = calloc(sizeof(struct ir_op), 1);
317 if (!op)
318 return NULL;
319 op->op = IR_OP_LOAD;
320 op->data_type = IR_DATA_EXPRESSION;
321 op->signedness = IR_SIGN_DYN;
322 op->side = side;
323 op->u.load.u.expression = create_load_expression(node);
324 if (!op->u.load.u.expression) {
325 goto error;
326 }
327 return op;
328
329 error:
330 free_load_expression(op->u.load.u.expression);
331 free(op);
332 return NULL;
333 }
334
335 static
336 struct ir_op *make_op_unary(enum unary_op_type unary_op_type,
337 const char *op_str, enum ir_op_signedness signedness,
338 struct ir_op *child, enum ir_side side)
339 {
340 struct ir_op *op = NULL;
341
342 if (child->data_type == IR_DATA_STRING) {
343 fprintf(stderr, "[error] unary operation '%s' not allowed on string literal\n", op_str);
344 goto error;
345 }
346
347 op = calloc(sizeof(struct ir_op), 1);
348 if (!op)
349 return NULL;
350 op->op = IR_OP_UNARY;
351 op->data_type = child->data_type;
352 op->signedness = signedness;
353 op->side = side;
354 op->u.unary.type = unary_op_type;
355 op->u.unary.child = child;
356 return op;
357
358 error:
359 free(op);
360 return NULL;
361 }
362
363 /*
364 * unary + is pretty much useless.
365 */
366 static
367 struct ir_op *make_op_unary_plus(struct ir_op *child, enum ir_side side)
368 {
369 return make_op_unary(AST_UNARY_PLUS, "+", child->signedness,
370 child, side);
371 }
372
373 static
374 struct ir_op *make_op_unary_minus(struct ir_op *child, enum ir_side side)
375 {
376 return make_op_unary(AST_UNARY_MINUS, "-", child->signedness,
377 child, side);
378 }
379
380 static
381 struct ir_op *make_op_unary_not(struct ir_op *child, enum ir_side side)
382 {
383 return make_op_unary(AST_UNARY_NOT, "!", child->signedness,
384 child, side);
385 }
386
387 static
388 struct ir_op *make_op_binary_compare(enum op_type bin_op_type,
389 const char *op_str, struct ir_op *left, struct ir_op *right,
390 enum ir_side side)
391 {
392 struct ir_op *op = NULL;
393
394 if (left->data_type == IR_DATA_UNKNOWN
395 || right->data_type == IR_DATA_UNKNOWN) {
396 fprintf(stderr, "[error] binary operation '%s' has unknown operand type\n", op_str);
397 goto error;
398
399 }
400 if ((left->data_type == IR_DATA_STRING
401 && (right->data_type == IR_DATA_NUMERIC || right->data_type == IR_DATA_FLOAT))
402 || ((left->data_type == IR_DATA_NUMERIC || left->data_type == IR_DATA_FLOAT) &&
403 right->data_type == IR_DATA_STRING)) {
404 fprintf(stderr, "[error] binary operation '%s' operand type mismatch\n", op_str);
405 goto error;
406 }
407
408 op = calloc(sizeof(struct ir_op), 1);
409 if (!op)
410 return NULL;
411 op->op = IR_OP_BINARY;
412 op->u.binary.type = bin_op_type;
413 op->u.binary.left = left;
414 op->u.binary.right = right;
415
416 /* we return a boolean, represented as signed numeric */
417 op->data_type = IR_DATA_NUMERIC;
418 op->signedness = IR_SIGNED;
419 op->side = side;
420
421 return op;
422
423 error:
424 free(op);
425 return NULL;
426 }
427
428 static
429 struct ir_op *make_op_binary_eq(struct ir_op *left, struct ir_op *right,
430 enum ir_side side)
431 {
432 return make_op_binary_compare(AST_OP_EQ, "==", left, right, side);
433 }
434
435 static
436 struct ir_op *make_op_binary_ne(struct ir_op *left, struct ir_op *right,
437 enum ir_side side)
438 {
439 return make_op_binary_compare(AST_OP_NE, "!=", left, right, side);
440 }
441
442 static
443 struct ir_op *make_op_binary_gt(struct ir_op *left, struct ir_op *right,
444 enum ir_side side)
445 {
446 return make_op_binary_compare(AST_OP_GT, ">", left, right, side);
447 }
448
449 static
450 struct ir_op *make_op_binary_lt(struct ir_op *left, struct ir_op *right,
451 enum ir_side side)
452 {
453 return make_op_binary_compare(AST_OP_LT, "<", left, right, side);
454 }
455
456 static
457 struct ir_op *make_op_binary_ge(struct ir_op *left, struct ir_op *right,
458 enum ir_side side)
459 {
460 return make_op_binary_compare(AST_OP_GE, ">=", left, right, side);
461 }
462
463 static
464 struct ir_op *make_op_binary_le(struct ir_op *left, struct ir_op *right,
465 enum ir_side side)
466 {
467 return make_op_binary_compare(AST_OP_LE, "<=", left, right, side);
468 }
469
470 static
471 struct ir_op *make_op_binary_logical(enum op_type bin_op_type,
472 const char *op_str, struct ir_op *left, struct ir_op *right,
473 enum ir_side side)
474 {
475 struct ir_op *op = NULL;
476
477 if (left->data_type == IR_DATA_UNKNOWN
478 || right->data_type == IR_DATA_UNKNOWN) {
479 fprintf(stderr, "[error] binary operation '%s' has unknown operand type\n", op_str);
480 goto error;
481
482 }
483 if (left->data_type == IR_DATA_STRING
484 || right->data_type == IR_DATA_STRING) {
485 fprintf(stderr, "[error] logical binary operation '%s' cannot have string operand\n", op_str);
486 goto error;
487 }
488
489 op = calloc(sizeof(struct ir_op), 1);
490 if (!op)
491 return NULL;
492 op->op = IR_OP_LOGICAL;
493 op->u.binary.type = bin_op_type;
494 op->u.binary.left = left;
495 op->u.binary.right = right;
496
497 /* we return a boolean, represented as signed numeric */
498 op->data_type = IR_DATA_NUMERIC;
499 op->signedness = IR_SIGNED;
500 op->side = side;
501
502 return op;
503
504 error:
505 free(op);
506 return NULL;
507 }
508
509 static
510 struct ir_op *make_op_binary_bitwise(enum op_type bin_op_type,
511 const char *op_str, struct ir_op *left, struct ir_op *right,
512 enum ir_side side)
513 {
514 struct ir_op *op = NULL;
515
516 if (left->data_type == IR_DATA_UNKNOWN
517 || right->data_type == IR_DATA_UNKNOWN) {
518 fprintf(stderr, "[error] bitwise binary operation '%s' has unknown operand type\n", op_str);
519 goto error;
520
521 }
522 if (left->data_type == IR_DATA_STRING
523 || right->data_type == IR_DATA_STRING) {
524 fprintf(stderr, "[error] bitwise binary operation '%s' cannot have string operand\n", op_str);
525 goto error;
526 }
527 if (left->data_type == IR_DATA_FLOAT
528 || right->data_type == IR_DATA_FLOAT) {
529 fprintf(stderr, "[error] bitwise binary operation '%s' cannot have floating point operand\n", op_str);
530 goto error;
531 }
532
533 op = calloc(sizeof(struct ir_op), 1);
534 if (!op)
535 return NULL;
536 op->op = IR_OP_BINARY;
537 op->u.binary.type = bin_op_type;
538 op->u.binary.left = left;
539 op->u.binary.right = right;
540
541 /* we return a signed numeric */
542 op->data_type = IR_DATA_NUMERIC;
543 op->signedness = IR_SIGNED;
544 op->side = side;
545
546 return op;
547
548 error:
549 free(op);
550 return NULL;
551 }
552
553 static
554 struct ir_op *make_op_binary_logical_and(struct ir_op *left, struct ir_op *right,
555 enum ir_side side)
556 {
557 return make_op_binary_logical(AST_OP_AND, "&&", left, right, side);
558 }
559
560 static
561 struct ir_op *make_op_binary_logical_or(struct ir_op *left, struct ir_op *right,
562 enum ir_side side)
563 {
564 return make_op_binary_logical(AST_OP_OR, "||", left, right, side);
565 }
566
567 static
568 struct ir_op *make_op_binary_bitwise_and(struct ir_op *left, struct ir_op *right,
569 enum ir_side side)
570 {
571 return make_op_binary_bitwise(AST_OP_BIT_AND, "&", left, right, side);
572 }
573
574 static
575 struct ir_op *make_op_binary_bitwise_or(struct ir_op *left, struct ir_op *right,
576 enum ir_side side)
577 {
578 return make_op_binary_bitwise(AST_OP_BIT_OR, "|", left, right, side);
579 }
580
581 static
582 struct ir_op *make_op_binary_bitwise_xor(struct ir_op *left, struct ir_op *right,
583 enum ir_side side)
584 {
585 return make_op_binary_bitwise(AST_OP_BIT_XOR, "^", left, right, side);
586 }
587
588 static
589 void filter_free_ir_recursive(struct ir_op *op)
590 {
591 if (!op)
592 return;
593 switch (op->op) {
594 case IR_OP_UNKNOWN:
595 default:
596 fprintf(stderr, "[error] Unknown op type in %s\n",
597 __func__);
598 break;
599 case IR_OP_ROOT:
600 filter_free_ir_recursive(op->u.root.child);
601 break;
602 case IR_OP_LOAD:
603 switch (op->data_type) {
604 case IR_DATA_STRING:
605 free(op->u.load.u.string.value);
606 break;
607 case IR_DATA_FIELD_REF: /* fall-through */
608 case IR_DATA_GET_CONTEXT_REF:
609 free(op->u.load.u.ref);
610 break;
611 case IR_DATA_EXPRESSION:
612 free_load_expression(op->u.load.u.expression);
613 default:
614 break;
615 }
616 break;
617 case IR_OP_UNARY:
618 filter_free_ir_recursive(op->u.unary.child);
619 break;
620 case IR_OP_BINARY:
621 filter_free_ir_recursive(op->u.binary.left);
622 filter_free_ir_recursive(op->u.binary.right);
623 break;
624 case IR_OP_LOGICAL:
625 filter_free_ir_recursive(op->u.logical.left);
626 filter_free_ir_recursive(op->u.logical.right);
627 break;
628 }
629 free(op);
630 }
631
632 static
633 struct ir_op *make_expression(struct filter_parser_ctx *ctx,
634 struct filter_node *node, enum ir_side side)
635 {
636 switch (node->u.expression.type) {
637 case AST_EXP_UNKNOWN:
638 default:
639 fprintf(stderr, "[error] %s: unknown expression type\n", __func__);
640 return NULL;
641
642 case AST_EXP_STRING:
643 return make_op_load_string(node->u.expression.u.string, side);
644 case AST_EXP_CONSTANT:
645 return make_op_load_numeric(node->u.expression.u.constant,
646 side);
647 case AST_EXP_FLOAT_CONSTANT:
648 return make_op_load_float(node->u.expression.u.float_constant,
649 side);
650 case AST_EXP_IDENTIFIER:
651 case AST_EXP_GLOBAL_IDENTIFIER:
652 return make_op_load_expression(node, side);
653 #if 0
654 switch (node->u.expression.pre_op) {
655 case AST_LINK_UNKNOWN:
656 return make_op_load_field_ref(node->u.expression.u.identifier,
657 side);
658 case AST_LINK_BRACKET:
659 return make_op_load_field_ref_index(node->u.expression.u.identifier,
660 node->u.expression.next,
661 side);
662 default:
663 fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__);
664 return NULL;
665 }
666 #endif
667 #if 0
668 {
669 const char *name;
670
671 /*
672 * We currently only support $ctx (context) and $app
673 * identifiers.
674 */
675 if (strncmp(node->u.expression.u.identifier,
676 "$ctx.", strlen("$ctx.")) != 0
677 && strncmp(node->u.expression.u.identifier,
678 "$app.", strlen("$app.")) != 0) {
679 fprintf(stderr, "[error] %s: \"%s\" global identifier is unknown. Only \"$ctx\" and \"$app\" are currently implemented.\n", __func__, node->u.expression.u.identifier);
680 return NULL;
681 }
682 name = strchr(node->u.expression.u.identifier, '.');
683 if (!name) {
684 fprintf(stderr, "[error] %s: Expecting '.'\n", __func__);
685 return NULL;
686 }
687 name++; /* Skip . */
688 if (!strlen(name)) {
689 fprintf(stderr, "[error] %s: Expecting a context name, e.g. \'$ctx.name\'.\n", __func__);
690 return NULL;
691 }
692 switch (node->u.expression.pre_op) {
693 case AST_LINK_UNKNOWN:
694 return make_op_load_get_context_ref(node->u.expression.u.identifier,
695 side);
696 case AST_LINK_BRACKET:
697 return make_op_load_get_context_ref_index(node->u.expression.u.identifier,
698 node->u.expression.next,
699 side);
700 default:
701 fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__);
702 return NULL;
703 }
704
705 }
706 #endif
707 case AST_EXP_NESTED:
708 return generate_ir_recursive(ctx, node->u.expression.u.child,
709 side);
710 }
711 }
712
713 static
714 struct ir_op *make_op(struct filter_parser_ctx *ctx,
715 struct filter_node *node, enum ir_side side)
716 {
717 struct ir_op *op = NULL, *lchild, *rchild;
718 const char *op_str = "?";
719
720 switch (node->u.op.type) {
721 case AST_OP_UNKNOWN:
722 default:
723 fprintf(stderr, "[error] %s: unknown binary op type\n", __func__);
724 return NULL;
725
726 /*
727 * The following binary operators other than comparators and
728 * logical and/or are not supported yet.
729 */
730 case AST_OP_MUL:
731 op_str = "*";
732 goto error_not_supported;
733 case AST_OP_DIV:
734 op_str = "/";
735 goto error_not_supported;
736 case AST_OP_MOD:
737 op_str = "%";
738 goto error_not_supported;
739 case AST_OP_PLUS:
740 op_str = "+";
741 goto error_not_supported;
742 case AST_OP_MINUS:
743 op_str = "-";
744 goto error_not_supported;
745 case AST_OP_RSHIFT:
746 op_str = ">>";
747 goto error_not_supported;
748 case AST_OP_LSHIFT:
749 op_str = "<<";
750 goto error_not_supported;
751
752 case AST_OP_BIT_AND:
753 case AST_OP_BIT_OR:
754 case AST_OP_BIT_XOR:
755 lchild = generate_ir_recursive(ctx, node->u.op.lchild, IR_LEFT);
756 if (!lchild)
757 return NULL;
758 rchild = generate_ir_recursive(ctx, node->u.op.rchild, IR_RIGHT);
759 if (!rchild) {
760 filter_free_ir_recursive(lchild);
761 return NULL;
762 }
763 break;
764
765 case AST_OP_EQ:
766 case AST_OP_NE:
767 case AST_OP_GT:
768 case AST_OP_LT:
769 case AST_OP_GE:
770 case AST_OP_LE:
771 lchild = generate_ir_recursive(ctx, node->u.op.lchild, IR_LEFT);
772 if (!lchild)
773 return NULL;
774 rchild = generate_ir_recursive(ctx, node->u.op.rchild, IR_RIGHT);
775 if (!rchild) {
776 filter_free_ir_recursive(lchild);
777 return NULL;
778 }
779 break;
780
781 case AST_OP_AND:
782 case AST_OP_OR:
783 /*
784 * Both children considered as left, since we need to
785 * populate R0.
786 */
787 lchild = generate_ir_recursive(ctx, node->u.op.lchild, IR_LEFT);
788 if (!lchild)
789 return NULL;
790 rchild = generate_ir_recursive(ctx, node->u.op.rchild, IR_LEFT);
791 if (!rchild) {
792 filter_free_ir_recursive(lchild);
793 return NULL;
794 }
795 break;
796 }
797
798 switch (node->u.op.type) {
799 case AST_OP_AND:
800 op = make_op_binary_logical_and(lchild, rchild, side);
801 break;
802 case AST_OP_OR:
803 op = make_op_binary_logical_or(lchild, rchild, side);
804 break;
805 case AST_OP_EQ:
806 op = make_op_binary_eq(lchild, rchild, side);
807 break;
808 case AST_OP_NE:
809 op = make_op_binary_ne(lchild, rchild, side);
810 break;
811 case AST_OP_GT:
812 op = make_op_binary_gt(lchild, rchild, side);
813 break;
814 case AST_OP_LT:
815 op = make_op_binary_lt(lchild, rchild, side);
816 break;
817 case AST_OP_GE:
818 op = make_op_binary_ge(lchild, rchild, side);
819 break;
820 case AST_OP_LE:
821 op = make_op_binary_le(lchild, rchild, side);
822 break;
823 case AST_OP_BIT_AND:
824 op = make_op_binary_bitwise_and(lchild, rchild, side);
825 break;
826 case AST_OP_BIT_OR:
827 op = make_op_binary_bitwise_or(lchild, rchild, side);
828 break;
829 case AST_OP_BIT_XOR:
830 op = make_op_binary_bitwise_xor(lchild, rchild, side);
831 break;
832 default:
833 break;
834 }
835
836 if (!op) {
837 filter_free_ir_recursive(rchild);
838 filter_free_ir_recursive(lchild);
839 }
840 return op;
841
842 error_not_supported:
843 fprintf(stderr, "[error] %s: binary operation '%s' not supported\n",
844 __func__, op_str);
845 return NULL;
846 }
847
848 static
849 struct ir_op *make_unary_op(struct filter_parser_ctx *ctx,
850 struct filter_node *node, enum ir_side side)
851 {
852 const char *op_str = "?";
853
854 switch (node->u.unary_op.type) {
855 case AST_UNARY_UNKNOWN:
856 default:
857 fprintf(stderr, "[error] %s: unknown unary op type\n", __func__);
858 return NULL;
859
860 case AST_UNARY_PLUS:
861 {
862 struct ir_op *op, *child;
863
864 child = generate_ir_recursive(ctx, node->u.unary_op.child,
865 side);
866 if (!child)
867 return NULL;
868 op = make_op_unary_plus(child, side);
869 if (!op) {
870 filter_free_ir_recursive(child);
871 return NULL;
872 }
873 return op;
874 }
875 case AST_UNARY_MINUS:
876 {
877 struct ir_op *op, *child;
878
879 child = generate_ir_recursive(ctx, node->u.unary_op.child,
880 side);
881 if (!child)
882 return NULL;
883 op = make_op_unary_minus(child, side);
884 if (!op) {
885 filter_free_ir_recursive(child);
886 return NULL;
887 }
888 return op;
889 }
890 case AST_UNARY_NOT:
891 {
892 struct ir_op *op, *child;
893
894 child = generate_ir_recursive(ctx, node->u.unary_op.child,
895 side);
896 if (!child)
897 return NULL;
898 op = make_op_unary_not(child, side);
899 if (!op) {
900 filter_free_ir_recursive(child);
901 return NULL;
902 }
903 return op;
904 }
905 case AST_UNARY_BIT_NOT:
906 {
907 op_str = "~";
908 goto error_not_supported;
909 }
910 }
911
912 error_not_supported:
913 fprintf(stderr, "[error] %s: unary operation '%s' not supported\n",
914 __func__, op_str);
915 return NULL;
916 }
917
918 static
919 struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx,
920 struct filter_node *node, enum ir_side side)
921 {
922 switch (node->type) {
923 case NODE_UNKNOWN:
924 default:
925 fprintf(stderr, "[error] %s: unknown node type\n", __func__);
926 return NULL;
927
928 case NODE_ROOT:
929 {
930 struct ir_op *op, *child;
931
932 child = generate_ir_recursive(ctx, node->u.root.child,
933 side);
934 if (!child)
935 return NULL;
936 op = make_op_root(child, side);
937 if (!op) {
938 filter_free_ir_recursive(child);
939 return NULL;
940 }
941 return op;
942 }
943 case NODE_EXPRESSION:
944 return make_expression(ctx, node, side);
945 case NODE_OP:
946 return make_op(ctx, node, side);
947 case NODE_UNARY_OP:
948 return make_unary_op(ctx, node, side);
949 }
950 return 0;
951 }
952
953 LTTNG_HIDDEN
954 void filter_ir_free(struct filter_parser_ctx *ctx)
955 {
956 filter_free_ir_recursive(ctx->ir_root);
957 ctx->ir_root = NULL;
958 }
959
960 LTTNG_HIDDEN
961 int filter_visitor_ir_generate(struct filter_parser_ctx *ctx)
962 {
963 struct ir_op *op;
964
965 op = generate_ir_recursive(ctx, &ctx->ast->root, IR_LEFT);
966 if (!op) {
967 return -EINVAL;
968 }
969 ctx->ir_root = op;
970 return 0;
971 }
This page took 0.072668 seconds and 6 git commands to generate.