2 * filter-visitor-generate-ir.c
4 * LTTng filter generate intermediate representation
6 * Copyright 2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
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.
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.
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
29 #include "filter-ast.h"
30 #include "filter-parser.h"
31 #include "filter-ir.h"
33 #include <common/macros.h>
34 #include <common/string-utils/string-utils.h>
37 struct ir_op
*generate_ir_recursive(struct filter_parser_ctx
*ctx
,
38 struct filter_node
*node
, enum ir_side side
);
41 struct ir_op
*make_op_root(struct ir_op
*child
, enum ir_side side
)
45 op
= calloc(sizeof(struct ir_op
), 1);
48 switch (child
->data_type
) {
51 fprintf(stderr
, "[error] Unknown root child data type\n");
55 fprintf(stderr
, "[error] String cannot be root data type\n");
59 case IR_DATA_FIELD_REF
:
60 case IR_DATA_GET_CONTEXT_REF
:
66 op
->data_type
= child
->data_type
;
67 op
->signedness
= child
->signedness
;
68 op
->u
.root
.child
= child
;
73 enum ir_load_string_type
get_literal_string_type(const char *string
)
77 if (strutils_is_star_glob_pattern(string
)) {
78 if (strutils_is_star_at_the_end_only_glob_pattern(string
)) {
79 return IR_LOAD_STRING_TYPE_GLOB_STAR_END
;
82 return IR_LOAD_STRING_TYPE_GLOB_STAR
;
85 return IR_LOAD_STRING_TYPE_PLAIN
;
89 struct ir_op
*make_op_load_string(char *string
, enum ir_side side
)
93 op
= calloc(sizeof(struct ir_op
), 1);
97 op
->data_type
= IR_DATA_STRING
;
98 op
->signedness
= IR_SIGN_UNKNOWN
;
100 op
->u
.load
.u
.string
.type
= get_literal_string_type(string
);
101 op
->u
.load
.u
.string
.value
= strdup(string
);
102 if (!op
->u
.load
.u
.string
.value
) {
110 struct ir_op
*make_op_load_numeric(int64_t v
, enum ir_side side
)
114 op
= calloc(sizeof(struct ir_op
), 1);
118 op
->data_type
= IR_DATA_NUMERIC
;
119 /* TODO: for now, all numeric values are signed */
120 op
->signedness
= IR_SIGNED
;
122 op
->u
.load
.u
.num
= v
;
127 struct ir_op
*make_op_load_float(double v
, enum ir_side side
)
131 op
= calloc(sizeof(struct ir_op
), 1);
135 op
->data_type
= IR_DATA_FLOAT
;
136 op
->signedness
= IR_SIGN_UNKNOWN
;
138 op
->u
.load
.u
.flt
= v
;
143 struct ir_op
*make_op_load_field_ref(char *string
,
148 op
= calloc(sizeof(struct ir_op
), 1);
152 op
->data_type
= IR_DATA_FIELD_REF
;
153 op
->signedness
= IR_SIGN_DYN
;
155 op
->u
.load
.u
.ref
= strdup(string
);
156 if (!op
->u
.load
.u
.ref
) {
167 struct ir_op
*make_op_load_field_ref_index(char *string
,
168 struct filter_node
*next
,
173 op
= calloc(sizeof(struct ir_op
), 1);
177 op
->data_type
= IR_DATA_FIELD_REF_INDEX
;
178 op
->signedness
= IR_SIGN_DYN
;
180 op
->u
.load
.u
.ref_index
.symbol
= strdup(string
);
181 if (!op
->u
.load
.u
.ref_index
.symbol
) {
184 /* Only positive integer literals accepted as index. */
185 if (next
->type
== NODE_UNARY_OP
) {
186 fprintf(stderr
, "[error] Unexpected unary operator as index\n");
189 if (next
->type
!= NODE_EXPRESSION
) {
190 fprintf(stderr
, "[error] Expecting expression as index\n");
193 if (next
->u
.expression
.type
!= AST_EXP_CONSTANT
) {
194 fprintf(stderr
, "[error] Expecting constant index\n");
197 if (next
->u
.expression
.u
.constant
< 0) {
198 fprintf(stderr
, "[error] Expecting positive constant index\n");
201 op
->u
.load
.u
.ref_index
.index
= next
->u
.expression
.u
.constant
;
210 struct ir_op
*make_op_load_get_context_ref(char *string
,
215 op
= calloc(sizeof(struct ir_op
), 1);
219 op
->data_type
= IR_DATA_GET_CONTEXT_REF
;
220 op
->signedness
= IR_SIGN_DYN
;
222 op
->u
.load
.u
.ref
= strdup(string
);
223 if (!op
->u
.load
.u
.ref
) {
234 struct ir_op
*make_op_load_get_context_ref_index(char *string
,
235 struct filter_node
*next
,
240 op
= calloc(sizeof(struct ir_op
), 1);
244 op
->data_type
= IR_DATA_GET_CONTEXT_REF_INDEX
;
245 op
->signedness
= IR_SIGN_DYN
;
247 op
->u
.load
.u
.ref_index
.symbol
= strdup(string
);
248 if (!op
->u
.load
.u
.ref_index
.symbol
) {
251 /* Only positive integer literals accepted as offset. */
252 if (next
->type
== NODE_UNARY_OP
) {
253 fprintf(stderr
, "[error] Unexpected unary operator as index\n");
256 if (next
->type
!= NODE_EXPRESSION
) {
257 fprintf(stderr
, "[error] Expecting expression as index\n");
260 if (next
->u
.expression
.type
!= AST_EXP_CONSTANT
) {
261 fprintf(stderr
, "[error] Expecting constant index\n");
264 if (next
->u
.expression
.u
.constant
< 0) {
265 fprintf(stderr
, "[error] Expecting positive constant index\n");
268 op
->u
.load
.u
.ref_index
.index
= next
->u
.expression
.u
.constant
;
277 struct ir_op
*make_op_unary(enum unary_op_type unary_op_type
,
278 const char *op_str
, enum ir_op_signedness signedness
,
279 struct ir_op
*child
, enum ir_side side
)
281 struct ir_op
*op
= NULL
;
283 if (child
->data_type
== IR_DATA_STRING
) {
284 fprintf(stderr
, "[error] unary operation '%s' not allowed on string literal\n", op_str
);
288 op
= calloc(sizeof(struct ir_op
), 1);
291 op
->op
= IR_OP_UNARY
;
292 op
->data_type
= child
->data_type
;
293 op
->signedness
= signedness
;
295 op
->u
.unary
.type
= unary_op_type
;
296 op
->u
.unary
.child
= child
;
305 * unary + is pretty much useless.
308 struct ir_op
*make_op_unary_plus(struct ir_op
*child
, enum ir_side side
)
310 return make_op_unary(AST_UNARY_PLUS
, "+", child
->signedness
,
315 struct ir_op
*make_op_unary_minus(struct ir_op
*child
, enum ir_side side
)
317 return make_op_unary(AST_UNARY_MINUS
, "-", child
->signedness
,
322 struct ir_op
*make_op_unary_not(struct ir_op
*child
, enum ir_side side
)
324 return make_op_unary(AST_UNARY_NOT
, "!", child
->signedness
,
329 struct ir_op
*make_op_binary_compare(enum op_type bin_op_type
,
330 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
333 struct ir_op
*op
= NULL
;
335 if (left
->data_type
== IR_DATA_UNKNOWN
336 || right
->data_type
== IR_DATA_UNKNOWN
) {
337 fprintf(stderr
, "[error] binary operation '%s' has unknown operand type\n", op_str
);
341 if ((left
->data_type
== IR_DATA_STRING
342 && (right
->data_type
== IR_DATA_NUMERIC
|| right
->data_type
== IR_DATA_FLOAT
))
343 || ((left
->data_type
== IR_DATA_NUMERIC
|| left
->data_type
== IR_DATA_FLOAT
) &&
344 right
->data_type
== IR_DATA_STRING
)) {
345 fprintf(stderr
, "[error] binary operation '%s' operand type mismatch\n", op_str
);
349 op
= calloc(sizeof(struct ir_op
), 1);
352 op
->op
= IR_OP_BINARY
;
353 op
->u
.binary
.type
= bin_op_type
;
354 op
->u
.binary
.left
= left
;
355 op
->u
.binary
.right
= right
;
357 /* we return a boolean, represented as signed numeric */
358 op
->data_type
= IR_DATA_NUMERIC
;
359 op
->signedness
= IR_SIGNED
;
370 struct ir_op
*make_op_binary_eq(struct ir_op
*left
, struct ir_op
*right
,
373 return make_op_binary_compare(AST_OP_EQ
, "==", left
, right
, side
);
377 struct ir_op
*make_op_binary_ne(struct ir_op
*left
, struct ir_op
*right
,
380 return make_op_binary_compare(AST_OP_NE
, "!=", left
, right
, side
);
384 struct ir_op
*make_op_binary_gt(struct ir_op
*left
, struct ir_op
*right
,
387 return make_op_binary_compare(AST_OP_GT
, ">", left
, right
, side
);
391 struct ir_op
*make_op_binary_lt(struct ir_op
*left
, struct ir_op
*right
,
394 return make_op_binary_compare(AST_OP_LT
, "<", left
, right
, side
);
398 struct ir_op
*make_op_binary_ge(struct ir_op
*left
, struct ir_op
*right
,
401 return make_op_binary_compare(AST_OP_GE
, ">=", left
, right
, side
);
405 struct ir_op
*make_op_binary_le(struct ir_op
*left
, struct ir_op
*right
,
408 return make_op_binary_compare(AST_OP_LE
, "<=", left
, right
, side
);
412 struct ir_op
*make_op_binary_logical(enum op_type bin_op_type
,
413 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
416 struct ir_op
*op
= NULL
;
418 if (left
->data_type
== IR_DATA_UNKNOWN
419 || right
->data_type
== IR_DATA_UNKNOWN
) {
420 fprintf(stderr
, "[error] binary operation '%s' has unknown operand type\n", op_str
);
424 if (left
->data_type
== IR_DATA_STRING
425 || right
->data_type
== IR_DATA_STRING
) {
426 fprintf(stderr
, "[error] logical binary operation '%s' cannot have string operand\n", op_str
);
430 op
= calloc(sizeof(struct ir_op
), 1);
433 op
->op
= IR_OP_LOGICAL
;
434 op
->u
.binary
.type
= bin_op_type
;
435 op
->u
.binary
.left
= left
;
436 op
->u
.binary
.right
= right
;
438 /* we return a boolean, represented as signed numeric */
439 op
->data_type
= IR_DATA_NUMERIC
;
440 op
->signedness
= IR_SIGNED
;
451 struct ir_op
*make_op_binary_logical_and(struct ir_op
*left
, struct ir_op
*right
,
454 return make_op_binary_logical(AST_OP_AND
, "&&", left
, right
, side
);
458 struct ir_op
*make_op_binary_logical_or(struct ir_op
*left
, struct ir_op
*right
,
461 return make_op_binary_logical(AST_OP_OR
, "||", left
, right
, side
);
465 void filter_free_ir_recursive(struct ir_op
*op
)
472 fprintf(stderr
, "[error] Unknown op type in %s\n",
476 filter_free_ir_recursive(op
->u
.root
.child
);
479 switch (op
->data_type
) {
481 free(op
->u
.load
.u
.string
.value
);
483 case IR_DATA_FIELD_REF
: /* fall-through */
484 case IR_DATA_GET_CONTEXT_REF
:
485 free(op
->u
.load
.u
.ref
);
487 case IR_DATA_FIELD_REF_INDEX
: /* fall-through */
488 case IR_DATA_GET_CONTEXT_REF_INDEX
:
489 free(op
->u
.load
.u
.ref_index
.symbol
);
496 filter_free_ir_recursive(op
->u
.unary
.child
);
499 filter_free_ir_recursive(op
->u
.binary
.left
);
500 filter_free_ir_recursive(op
->u
.binary
.right
);
503 filter_free_ir_recursive(op
->u
.logical
.left
);
504 filter_free_ir_recursive(op
->u
.logical
.right
);
511 struct ir_op
*make_expression(struct filter_parser_ctx
*ctx
,
512 struct filter_node
*node
, enum ir_side side
)
514 switch (node
->u
.expression
.type
) {
515 case AST_EXP_UNKNOWN
:
517 fprintf(stderr
, "[error] %s: unknown expression type\n", __func__
);
521 return make_op_load_string(node
->u
.expression
.u
.string
, side
);
522 case AST_EXP_CONSTANT
:
523 return make_op_load_numeric(node
->u
.expression
.u
.constant
,
525 case AST_EXP_FLOAT_CONSTANT
:
526 return make_op_load_float(node
->u
.expression
.u
.float_constant
,
528 case AST_EXP_IDENTIFIER
:
529 switch (node
->u
.expression
.pre_op
) {
530 case AST_LINK_UNKNOWN
:
531 return make_op_load_field_ref(node
->u
.expression
.u
.identifier
,
533 case AST_LINK_BRACKET
:
534 return make_op_load_field_ref_index(node
->u
.expression
.u
.identifier
,
535 node
->u
.expression
.next
,
538 fprintf(stderr
, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__
);
541 case AST_EXP_GLOBAL_IDENTIFIER
:
546 * We currently only support $ctx (context) and $app
549 if (strncmp(node
->u
.expression
.u
.identifier
,
550 "$ctx.", strlen("$ctx.")) != 0
551 && strncmp(node
->u
.expression
.u
.identifier
,
552 "$app.", strlen("$app.")) != 0) {
553 fprintf(stderr
, "[error] %s: \"%s\" global identifier is unknown. Only \"$ctx\" and \"$app\" are currently implemented.\n", __func__
, node
->u
.expression
.u
.identifier
);
556 name
= strchr(node
->u
.expression
.u
.identifier
, '.');
558 fprintf(stderr
, "[error] %s: Expecting '.'\n", __func__
);
563 fprintf(stderr
, "[error] %s: Expecting a context name, e.g. \'$ctx.name\'.\n", __func__
);
566 switch (node
->u
.expression
.pre_op
) {
567 case AST_LINK_UNKNOWN
:
568 return make_op_load_get_context_ref(node
->u
.expression
.u
.identifier
,
570 case AST_LINK_BRACKET
:
571 return make_op_load_get_context_ref_index(node
->u
.expression
.u
.identifier
,
572 node
->u
.expression
.next
,
575 fprintf(stderr
, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__
);
581 return generate_ir_recursive(ctx
, node
->u
.expression
.u
.child
,
587 struct ir_op
*make_op(struct filter_parser_ctx
*ctx
,
588 struct filter_node
*node
, enum ir_side side
)
590 struct ir_op
*op
= NULL
, *lchild
, *rchild
;
591 const char *op_str
= "?";
593 switch (node
->u
.op
.type
) {
596 fprintf(stderr
, "[error] %s: unknown binary op type\n", __func__
);
600 * Binary operators other than comparators and logical and/or
601 * are not supported. If we ever want to support those, we will
602 * need a stack for the general case rather than just 2
603 * registers (see bytecode).
607 goto error_not_supported
;
610 goto error_not_supported
;
613 goto error_not_supported
;
616 goto error_not_supported
;
619 goto error_not_supported
;
622 goto error_not_supported
;
625 goto error_not_supported
;
628 goto error_not_supported
;
631 goto error_not_supported
;
634 goto error_not_supported
;
642 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
645 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_RIGHT
);
647 filter_free_ir_recursive(lchild
);
655 * Both children considered as left, since we need to
658 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
661 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_LEFT
);
663 filter_free_ir_recursive(lchild
);
669 switch (node
->u
.op
.type
) {
671 op
= make_op_binary_logical_and(lchild
, rchild
, side
);
674 op
= make_op_binary_logical_or(lchild
, rchild
, side
);
677 op
= make_op_binary_eq(lchild
, rchild
, side
);
680 op
= make_op_binary_ne(lchild
, rchild
, side
);
683 op
= make_op_binary_gt(lchild
, rchild
, side
);
686 op
= make_op_binary_lt(lchild
, rchild
, side
);
689 op
= make_op_binary_ge(lchild
, rchild
, side
);
692 op
= make_op_binary_le(lchild
, rchild
, side
);
699 filter_free_ir_recursive(rchild
);
700 filter_free_ir_recursive(lchild
);
705 fprintf(stderr
, "[error] %s: binary operation '%s' not supported\n",
711 struct ir_op
*make_unary_op(struct filter_parser_ctx
*ctx
,
712 struct filter_node
*node
, enum ir_side side
)
714 const char *op_str
= "?";
716 switch (node
->u
.unary_op
.type
) {
717 case AST_UNARY_UNKNOWN
:
719 fprintf(stderr
, "[error] %s: unknown unary op type\n", __func__
);
724 struct ir_op
*op
, *child
;
726 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
730 op
= make_op_unary_plus(child
, side
);
732 filter_free_ir_recursive(child
);
737 case AST_UNARY_MINUS
:
739 struct ir_op
*op
, *child
;
741 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
745 op
= make_op_unary_minus(child
, side
);
747 filter_free_ir_recursive(child
);
754 struct ir_op
*op
, *child
;
756 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
760 op
= make_op_unary_not(child
, side
);
762 filter_free_ir_recursive(child
);
767 case AST_UNARY_BIN_NOT
:
770 goto error_not_supported
;
775 fprintf(stderr
, "[error] %s: unary operation '%s' not supported\n",
781 struct ir_op
*generate_ir_recursive(struct filter_parser_ctx
*ctx
,
782 struct filter_node
*node
, enum ir_side side
)
784 switch (node
->type
) {
787 fprintf(stderr
, "[error] %s: unknown node type\n", __func__
);
792 struct ir_op
*op
, *child
;
794 child
= generate_ir_recursive(ctx
, node
->u
.root
.child
,
798 op
= make_op_root(child
, side
);
800 filter_free_ir_recursive(child
);
805 case NODE_EXPRESSION
:
806 return make_expression(ctx
, node
, side
);
808 return make_op(ctx
, node
, side
);
810 return make_unary_op(ctx
, node
, side
);
816 void filter_ir_free(struct filter_parser_ctx
*ctx
)
818 filter_free_ir_recursive(ctx
->ir_root
);
823 int filter_visitor_ir_generate(struct filter_parser_ctx
*ctx
)
827 op
= generate_ir_recursive(ctx
, &ctx
->ast
->root
, IR_LEFT
);