Fix: Delete stream on write error in consumer
[lttng-tools.git] / src / lib / lttng-ctl / filter / filter-visitor-generate-ir.c
CommitLineData
953192ba
MD
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>
953192ba 29#include "filter-ast.h"
95b9bd90 30#include "filter-parser.h"
953192ba
MD
31#include "filter-ir.h"
32
33static
34struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx,
35 struct filter_node *node, enum ir_side side);
36
37static
38struct 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
66static
67struct 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
86static
87struct 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
e90d8561
MD
103static
104struct 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
953192ba
MD
119static
120struct 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
139static
140struct 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
162error:
163 free(op);
164 return NULL;
165}
166
167/*
168 * unary + is pretty much useless.
169 */
170static
171struct 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
177static
178struct 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
184static
185struct 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
192static
193struct 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
243error:
244 free(op);
245 return NULL;
246}
247
248static
249struct 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
255static
256struct 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
262static
263struct 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
269static
270struct 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
276static
277struct 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
283static
284struct 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
290static
291struct 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
297static
298struct 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
304static
305struct 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
311static
312struct 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
319static
320struct 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
e90d8561
MD
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) &&
953192ba
MD
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
355error:
356 free(op);
357 return NULL;
358}
359
360static
361struct 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
367static
368struct 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
374static
375struct 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
381static
382struct 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
388static
389struct 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
395static
396struct 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
402static
403struct 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
436error:
437 free(op);
438 return NULL;
439}
440
441static
442struct 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
448static
449struct 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
455static
456void 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
496static
497struct 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);
e90d8561
MD
511 case AST_EXP_FLOAT_CONSTANT:
512 return make_op_load_float(node->u.expression.u.float_constant,
513 side);
953192ba
MD
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
527static
528struct 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
645error_not_supported:
646 fprintf(stderr, "[error] %s: binary operation '%s' not supported\n",
647 __func__, op_str);
648 return NULL;
649}
650
651static
652struct ir_op *make_unary_op(struct filter_parser_ctx *ctx,
653 struct filter_node *node, enum ir_side side)
654{
ab78f161
CB
655 const char *op_str = "?";
656
953192ba
MD
657 switch (node->u.unary_op.type) {
658 case AST_UNARY_UNKNOWN:
659 default:
660 fprintf(stderr, "[error] %s: unknown unary op type\n", __func__);
661 return NULL;
662
663 case AST_UNARY_PLUS:
664 {
665 struct ir_op *op, *child;
666
667 child = generate_ir_recursive(ctx, node->u.unary_op.child,
668 side);
669 if (!child)
670 return NULL;
671 op = make_op_unary_plus(child, side);
672 if (!op) {
673 filter_free_ir_recursive(child);
674 return NULL;
675 }
676 return op;
677 }
678 case AST_UNARY_MINUS:
679 {
680 struct ir_op *op, *child;
681
682 child = generate_ir_recursive(ctx, node->u.unary_op.child,
683 side);
684 if (!child)
685 return NULL;
686 op = make_op_unary_minus(child, side);
687 if (!op) {
688 filter_free_ir_recursive(child);
689 return NULL;
690 }
691 return op;
692 }
693 case AST_UNARY_NOT:
694 {
695 struct ir_op *op, *child;
696
697 child = generate_ir_recursive(ctx, node->u.unary_op.child,
698 side);
699 if (!child)
700 return NULL;
701 op = make_op_unary_not(child, side);
702 if (!op) {
703 filter_free_ir_recursive(child);
704 return NULL;
705 }
706 return op;
707 }
ab78f161
CB
708 case AST_UNARY_BIN_NOT:
709 {
710 op_str = "~";
711 goto error_not_supported;
712 }
953192ba 713 }
ab78f161
CB
714
715error_not_supported:
716 fprintf(stderr, "[error] %s: unary operation '%s' not supported\n",
717 __func__, op_str);
718 return NULL;
953192ba
MD
719}
720
721static
722struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx,
723 struct filter_node *node, enum ir_side side)
724{
725 switch (node->type) {
726 case NODE_UNKNOWN:
727 default:
728 fprintf(stderr, "[error] %s: unknown node type\n", __func__);
729 return NULL;
730
731 case NODE_ROOT:
732 {
733 struct ir_op *op, *child;
734
735 child = generate_ir_recursive(ctx, node->u.root.child,
736 side);
737 if (!child)
738 return NULL;
739 op = make_op_root(child, side);
740 if (!op) {
741 filter_free_ir_recursive(child);
742 return NULL;
743 }
744 return op;
745 }
746 case NODE_EXPRESSION:
747 return make_expression(ctx, node, side);
748 case NODE_OP:
749 return make_op(ctx, node, side);
750 case NODE_UNARY_OP:
751 return make_unary_op(ctx, node, side);
752 }
753 return 0;
754}
755
d00c599e 756__attribute__((visibility("hidden")))
953192ba
MD
757void filter_ir_free(struct filter_parser_ctx *ctx)
758{
759 filter_free_ir_recursive(ctx->ir_root);
760 ctx->ir_root = NULL;
761}
762
d00c599e 763__attribute__((visibility("hidden")))
953192ba
MD
764int filter_visitor_ir_generate(struct filter_parser_ctx *ctx)
765{
766 struct ir_op *op;
767
768 op = generate_ir_recursive(ctx, &ctx->ast->root, IR_LEFT);
769 if (!op) {
770 return -EINVAL;
771 }
772 ctx->ir_root = op;
773 return 0;
774}
This page took 0.050954 seconds and 4 git commands to generate.