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