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