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