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