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
:
61 case IR_DATA_EXPRESSION
:
67 op
->data_type
= child
->data_type
;
68 op
->signedness
= child
->signedness
;
69 op
->u
.root
.child
= child
;
74 enum ir_load_string_type
get_literal_string_type(const char *string
)
78 if (strutils_is_star_glob_pattern(string
)) {
79 if (strutils_is_star_at_the_end_only_glob_pattern(string
)) {
80 return IR_LOAD_STRING_TYPE_GLOB_STAR_END
;
83 return IR_LOAD_STRING_TYPE_GLOB_STAR
;
86 return IR_LOAD_STRING_TYPE_PLAIN
;
90 struct ir_op
*make_op_load_string(char *string
, enum ir_side side
)
94 op
= calloc(sizeof(struct ir_op
), 1);
98 op
->data_type
= IR_DATA_STRING
;
99 op
->signedness
= IR_SIGN_UNKNOWN
;
101 op
->u
.load
.u
.string
.type
= get_literal_string_type(string
);
102 op
->u
.load
.u
.string
.value
= strdup(string
);
103 if (!op
->u
.load
.u
.string
.value
) {
111 struct ir_op
*make_op_load_numeric(int64_t v
, enum ir_side side
)
115 op
= calloc(sizeof(struct ir_op
), 1);
119 op
->data_type
= IR_DATA_NUMERIC
;
120 /* TODO: for now, all numeric values are signed */
121 op
->signedness
= IR_SIGNED
;
123 op
->u
.load
.u
.num
= v
;
128 struct ir_op
*make_op_load_float(double v
, enum ir_side side
)
132 op
= calloc(sizeof(struct ir_op
), 1);
136 op
->data_type
= IR_DATA_FLOAT
;
137 op
->signedness
= IR_SIGN_UNKNOWN
;
139 op
->u
.load
.u
.flt
= v
;
145 struct ir_op
*make_op_load_field_ref(char *string
,
150 op
= calloc(sizeof(struct ir_op
), 1);
154 op
->data_type
= IR_DATA_FIELD_REF
;
155 op
->signedness
= IR_SIGN_DYN
;
157 op
->u
.load
.u
.ref
= strdup(string
);
158 if (!op
->u
.load
.u
.ref
) {
170 void free_load_expression(struct ir_load_expression
*load_expression
)
172 struct ir_load_expression_op
*exp_op
;
174 if (!load_expression
)
176 exp_op
= load_expression
->child
;
178 struct ir_load_expression_op
*prev_exp_op
;
182 switch (exp_op
->type
) {
183 case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT
:
184 case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT
:
185 case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT
:
186 case IR_LOAD_EXPRESSION_GET_INDEX
:
187 case IR_LOAD_EXPRESSION_LOAD_FIELD
:
189 case IR_LOAD_EXPRESSION_GET_SYMBOL
:
190 free(exp_op
->u
.symbol
);
193 prev_exp_op
= exp_op
;
194 exp_op
= exp_op
->next
;
197 free(load_expression
);
201 * Returns the first node of the chain, after initializing the next
205 struct filter_node
*load_expression_get_forward_chain(struct filter_node
*node
)
207 struct filter_node
*prev_node
;
210 assert(node
->type
== NODE_EXPRESSION
);
212 node
= node
->u
.expression
.prev
;
216 node
->u
.expression
.next
= prev_node
;
222 struct ir_load_expression
*create_load_expression(struct filter_node
*node
)
224 struct ir_load_expression
*load_exp
;
225 struct ir_load_expression_op
*load_exp_op
, *prev_op
;
228 /* Get forward chain. */
229 node
= load_expression_get_forward_chain(node
);
232 load_exp
= calloc(sizeof(struct ir_load_expression
), 1);
237 load_exp_op
= calloc(sizeof(struct ir_load_expression_op
), 1);
240 load_exp
->child
= load_exp_op
;
241 str
= node
->u
.expression
.u
.string
;
242 if (!strcmp(str
, "$ctx")) {
243 load_exp_op
->type
= IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT
;
244 node
= node
->u
.expression
.next
;
246 fprintf(stderr
, "[error] Expecting identifier after \'%s\'\n", str
);
249 str
= node
->u
.expression
.u
.string
;
250 } else if (!strcmp(str
, "$app")) {
251 load_exp_op
->type
= IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT
;
252 node
= node
->u
.expression
.next
;
254 fprintf(stderr
, "[error] Expecting identifier after \'%s\'\n", str
);
257 str
= node
->u
.expression
.u
.string
;
258 } else if (str
[0] == '$') {
259 fprintf(stderr
, "[error] Unexpected identifier \'%s\'\n", str
);
262 load_exp_op
->type
= IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT
;
266 struct filter_node
*bracket_node
;
268 prev_op
= load_exp_op
;
269 load_exp_op
= calloc(sizeof(struct ir_load_expression_op
), 1);
272 prev_op
->next
= load_exp_op
;
273 load_exp_op
->type
= IR_LOAD_EXPRESSION_GET_SYMBOL
;
274 load_exp_op
->u
.symbol
= strdup(str
);
275 if (!load_exp_op
->u
.symbol
)
278 /* Explore brackets from current node. */
279 for (bracket_node
= node
->u
.expression
.next_bracket
;
280 bracket_node
!= NULL
;
281 bracket_node
= bracket_node
->u
.expression
.next_bracket
) {
282 prev_op
= load_exp_op
;
283 load_exp_op
= calloc(sizeof(struct ir_load_expression_op
), 1);
286 prev_op
->next
= load_exp_op
;
287 load_exp_op
->type
= IR_LOAD_EXPRESSION_GET_INDEX
;
288 load_exp_op
->u
.index
= bracket_node
->u
.expression
.u
.constant
;
290 /* Go to next chain element. */
291 node
= node
->u
.expression
.next
;
294 str
= node
->u
.expression
.u
.string
;
296 /* Add final load field */
297 prev_op
= load_exp_op
;
298 load_exp_op
= calloc(sizeof(struct ir_load_expression_op
), 1);
301 prev_op
->next
= load_exp_op
;
302 load_exp_op
->type
= IR_LOAD_EXPRESSION_LOAD_FIELD
;
306 free_load_expression(load_exp
);
311 struct ir_op
*make_op_load_expression(struct filter_node
*node
,
316 op
= calloc(sizeof(struct ir_op
), 1);
320 op
->data_type
= IR_DATA_EXPRESSION
;
321 op
->signedness
= IR_SIGN_DYN
;
323 op
->u
.load
.u
.expression
= create_load_expression(node
);
324 if (!op
->u
.load
.u
.expression
) {
330 free_load_expression(op
->u
.load
.u
.expression
);
336 struct ir_op
*make_op_unary(enum unary_op_type unary_op_type
,
337 const char *op_str
, enum ir_op_signedness signedness
,
338 struct ir_op
*child
, enum ir_side side
)
340 struct ir_op
*op
= NULL
;
342 if (child
->data_type
== IR_DATA_STRING
) {
343 fprintf(stderr
, "[error] unary operation '%s' not allowed on string literal\n", op_str
);
347 op
= calloc(sizeof(struct ir_op
), 1);
350 op
->op
= IR_OP_UNARY
;
351 op
->data_type
= child
->data_type
;
352 op
->signedness
= signedness
;
354 op
->u
.unary
.type
= unary_op_type
;
355 op
->u
.unary
.child
= child
;
364 * unary + is pretty much useless.
367 struct ir_op
*make_op_unary_plus(struct ir_op
*child
, enum ir_side side
)
369 return make_op_unary(AST_UNARY_PLUS
, "+", child
->signedness
,
374 struct ir_op
*make_op_unary_minus(struct ir_op
*child
, enum ir_side side
)
376 return make_op_unary(AST_UNARY_MINUS
, "-", child
->signedness
,
381 struct ir_op
*make_op_unary_not(struct ir_op
*child
, enum ir_side side
)
383 return make_op_unary(AST_UNARY_NOT
, "!", child
->signedness
,
388 struct ir_op
*make_op_binary_compare(enum op_type bin_op_type
,
389 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
392 struct ir_op
*op
= NULL
;
394 if (left
->data_type
== IR_DATA_UNKNOWN
395 || right
->data_type
== IR_DATA_UNKNOWN
) {
396 fprintf(stderr
, "[error] binary operation '%s' has unknown operand type\n", op_str
);
400 if ((left
->data_type
== IR_DATA_STRING
401 && (right
->data_type
== IR_DATA_NUMERIC
|| right
->data_type
== IR_DATA_FLOAT
))
402 || ((left
->data_type
== IR_DATA_NUMERIC
|| left
->data_type
== IR_DATA_FLOAT
) &&
403 right
->data_type
== IR_DATA_STRING
)) {
404 fprintf(stderr
, "[error] binary operation '%s' operand type mismatch\n", op_str
);
408 op
= calloc(sizeof(struct ir_op
), 1);
411 op
->op
= IR_OP_BINARY
;
412 op
->u
.binary
.type
= bin_op_type
;
413 op
->u
.binary
.left
= left
;
414 op
->u
.binary
.right
= right
;
416 /* we return a boolean, represented as signed numeric */
417 op
->data_type
= IR_DATA_NUMERIC
;
418 op
->signedness
= IR_SIGNED
;
429 struct ir_op
*make_op_binary_eq(struct ir_op
*left
, struct ir_op
*right
,
432 return make_op_binary_compare(AST_OP_EQ
, "==", left
, right
, side
);
436 struct ir_op
*make_op_binary_ne(struct ir_op
*left
, struct ir_op
*right
,
439 return make_op_binary_compare(AST_OP_NE
, "!=", left
, right
, side
);
443 struct ir_op
*make_op_binary_gt(struct ir_op
*left
, struct ir_op
*right
,
446 return make_op_binary_compare(AST_OP_GT
, ">", left
, right
, side
);
450 struct ir_op
*make_op_binary_lt(struct ir_op
*left
, struct ir_op
*right
,
453 return make_op_binary_compare(AST_OP_LT
, "<", left
, right
, side
);
457 struct ir_op
*make_op_binary_ge(struct ir_op
*left
, struct ir_op
*right
,
460 return make_op_binary_compare(AST_OP_GE
, ">=", left
, right
, side
);
464 struct ir_op
*make_op_binary_le(struct ir_op
*left
, struct ir_op
*right
,
467 return make_op_binary_compare(AST_OP_LE
, "<=", left
, right
, side
);
471 struct ir_op
*make_op_binary_logical(enum op_type bin_op_type
,
472 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
475 struct ir_op
*op
= NULL
;
477 if (left
->data_type
== IR_DATA_UNKNOWN
478 || right
->data_type
== IR_DATA_UNKNOWN
) {
479 fprintf(stderr
, "[error] binary operation '%s' has unknown operand type\n", op_str
);
483 if (left
->data_type
== IR_DATA_STRING
484 || right
->data_type
== IR_DATA_STRING
) {
485 fprintf(stderr
, "[error] logical binary operation '%s' cannot have string operand\n", op_str
);
489 op
= calloc(sizeof(struct ir_op
), 1);
492 op
->op
= IR_OP_LOGICAL
;
493 op
->u
.binary
.type
= bin_op_type
;
494 op
->u
.binary
.left
= left
;
495 op
->u
.binary
.right
= right
;
497 /* we return a boolean, represented as signed numeric */
498 op
->data_type
= IR_DATA_NUMERIC
;
499 op
->signedness
= IR_SIGNED
;
510 struct ir_op
*make_op_binary_bitwise(enum op_type bin_op_type
,
511 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
514 struct ir_op
*op
= NULL
;
516 if (left
->data_type
== IR_DATA_UNKNOWN
517 || right
->data_type
== IR_DATA_UNKNOWN
) {
518 fprintf(stderr
, "[error] bitwise binary operation '%s' has unknown operand type\n", op_str
);
522 if (left
->data_type
== IR_DATA_STRING
523 || right
->data_type
== IR_DATA_STRING
) {
524 fprintf(stderr
, "[error] bitwise binary operation '%s' cannot have string operand\n", op_str
);
527 if (left
->data_type
== IR_DATA_FLOAT
528 || right
->data_type
== IR_DATA_FLOAT
) {
529 fprintf(stderr
, "[error] bitwise binary operation '%s' cannot have floating point operand\n", op_str
);
533 op
= calloc(sizeof(struct ir_op
), 1);
536 op
->op
= IR_OP_BINARY
;
537 op
->u
.binary
.type
= bin_op_type
;
538 op
->u
.binary
.left
= left
;
539 op
->u
.binary
.right
= right
;
541 /* we return a signed numeric */
542 op
->data_type
= IR_DATA_NUMERIC
;
543 op
->signedness
= IR_SIGNED
;
554 struct ir_op
*make_op_binary_logical_and(struct ir_op
*left
, struct ir_op
*right
,
557 return make_op_binary_logical(AST_OP_AND
, "&&", left
, right
, side
);
561 struct ir_op
*make_op_binary_logical_or(struct ir_op
*left
, struct ir_op
*right
,
564 return make_op_binary_logical(AST_OP_OR
, "||", left
, right
, side
);
568 struct ir_op
*make_op_binary_bitwise_and(struct ir_op
*left
, struct ir_op
*right
,
571 return make_op_binary_bitwise(AST_OP_BIT_AND
, "&", left
, right
, side
);
575 struct ir_op
*make_op_binary_bitwise_or(struct ir_op
*left
, struct ir_op
*right
,
578 return make_op_binary_bitwise(AST_OP_BIT_OR
, "|", left
, right
, side
);
582 struct ir_op
*make_op_binary_bitwise_xor(struct ir_op
*left
, struct ir_op
*right
,
585 return make_op_binary_bitwise(AST_OP_BIT_XOR
, "^", left
, right
, side
);
589 void filter_free_ir_recursive(struct ir_op
*op
)
596 fprintf(stderr
, "[error] Unknown op type in %s\n",
600 filter_free_ir_recursive(op
->u
.root
.child
);
603 switch (op
->data_type
) {
605 free(op
->u
.load
.u
.string
.value
);
607 case IR_DATA_FIELD_REF
: /* fall-through */
608 case IR_DATA_GET_CONTEXT_REF
:
609 free(op
->u
.load
.u
.ref
);
611 case IR_DATA_EXPRESSION
:
612 free_load_expression(op
->u
.load
.u
.expression
);
618 filter_free_ir_recursive(op
->u
.unary
.child
);
621 filter_free_ir_recursive(op
->u
.binary
.left
);
622 filter_free_ir_recursive(op
->u
.binary
.right
);
625 filter_free_ir_recursive(op
->u
.logical
.left
);
626 filter_free_ir_recursive(op
->u
.logical
.right
);
633 struct ir_op
*make_expression(struct filter_parser_ctx
*ctx
,
634 struct filter_node
*node
, enum ir_side side
)
636 switch (node
->u
.expression
.type
) {
637 case AST_EXP_UNKNOWN
:
639 fprintf(stderr
, "[error] %s: unknown expression type\n", __func__
);
643 return make_op_load_string(node
->u
.expression
.u
.string
, side
);
644 case AST_EXP_CONSTANT
:
645 return make_op_load_numeric(node
->u
.expression
.u
.constant
,
647 case AST_EXP_FLOAT_CONSTANT
:
648 return make_op_load_float(node
->u
.expression
.u
.float_constant
,
650 case AST_EXP_IDENTIFIER
:
651 case AST_EXP_GLOBAL_IDENTIFIER
:
652 return make_op_load_expression(node
, side
);
654 switch (node
->u
.expression
.pre_op
) {
655 case AST_LINK_UNKNOWN
:
656 return make_op_load_field_ref(node
->u
.expression
.u
.identifier
,
658 case AST_LINK_BRACKET
:
659 return make_op_load_field_ref_index(node
->u
.expression
.u
.identifier
,
660 node
->u
.expression
.next
,
663 fprintf(stderr
, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__
);
672 * We currently only support $ctx (context) and $app
675 if (strncmp(node
->u
.expression
.u
.identifier
,
676 "$ctx.", strlen("$ctx.")) != 0
677 && strncmp(node
->u
.expression
.u
.identifier
,
678 "$app.", strlen("$app.")) != 0) {
679 fprintf(stderr
, "[error] %s: \"%s\" global identifier is unknown. Only \"$ctx\" and \"$app\" are currently implemented.\n", __func__
, node
->u
.expression
.u
.identifier
);
682 name
= strchr(node
->u
.expression
.u
.identifier
, '.');
684 fprintf(stderr
, "[error] %s: Expecting '.'\n", __func__
);
689 fprintf(stderr
, "[error] %s: Expecting a context name, e.g. \'$ctx.name\'.\n", __func__
);
692 switch (node
->u
.expression
.pre_op
) {
693 case AST_LINK_UNKNOWN
:
694 return make_op_load_get_context_ref(node
->u
.expression
.u
.identifier
,
696 case AST_LINK_BRACKET
:
697 return make_op_load_get_context_ref_index(node
->u
.expression
.u
.identifier
,
698 node
->u
.expression
.next
,
701 fprintf(stderr
, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__
);
708 return generate_ir_recursive(ctx
, node
->u
.expression
.u
.child
,
714 struct ir_op
*make_op(struct filter_parser_ctx
*ctx
,
715 struct filter_node
*node
, enum ir_side side
)
717 struct ir_op
*op
= NULL
, *lchild
, *rchild
;
718 const char *op_str
= "?";
720 switch (node
->u
.op
.type
) {
723 fprintf(stderr
, "[error] %s: unknown binary op type\n", __func__
);
727 * The following binary operators other than comparators and
728 * logical and/or are not supported yet.
732 goto error_not_supported
;
735 goto error_not_supported
;
738 goto error_not_supported
;
741 goto error_not_supported
;
744 goto error_not_supported
;
747 goto error_not_supported
;
750 goto error_not_supported
;
755 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
758 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_RIGHT
);
760 filter_free_ir_recursive(lchild
);
771 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
774 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_RIGHT
);
776 filter_free_ir_recursive(lchild
);
784 * Both children considered as left, since we need to
787 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
790 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_LEFT
);
792 filter_free_ir_recursive(lchild
);
798 switch (node
->u
.op
.type
) {
800 op
= make_op_binary_logical_and(lchild
, rchild
, side
);
803 op
= make_op_binary_logical_or(lchild
, rchild
, side
);
806 op
= make_op_binary_eq(lchild
, rchild
, side
);
809 op
= make_op_binary_ne(lchild
, rchild
, side
);
812 op
= make_op_binary_gt(lchild
, rchild
, side
);
815 op
= make_op_binary_lt(lchild
, rchild
, side
);
818 op
= make_op_binary_ge(lchild
, rchild
, side
);
821 op
= make_op_binary_le(lchild
, rchild
, side
);
824 op
= make_op_binary_bitwise_and(lchild
, rchild
, side
);
827 op
= make_op_binary_bitwise_or(lchild
, rchild
, side
);
830 op
= make_op_binary_bitwise_xor(lchild
, rchild
, side
);
837 filter_free_ir_recursive(rchild
);
838 filter_free_ir_recursive(lchild
);
843 fprintf(stderr
, "[error] %s: binary operation '%s' not supported\n",
849 struct ir_op
*make_unary_op(struct filter_parser_ctx
*ctx
,
850 struct filter_node
*node
, enum ir_side side
)
852 const char *op_str
= "?";
854 switch (node
->u
.unary_op
.type
) {
855 case AST_UNARY_UNKNOWN
:
857 fprintf(stderr
, "[error] %s: unknown unary op type\n", __func__
);
862 struct ir_op
*op
, *child
;
864 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
868 op
= make_op_unary_plus(child
, side
);
870 filter_free_ir_recursive(child
);
875 case AST_UNARY_MINUS
:
877 struct ir_op
*op
, *child
;
879 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
883 op
= make_op_unary_minus(child
, side
);
885 filter_free_ir_recursive(child
);
892 struct ir_op
*op
, *child
;
894 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
898 op
= make_op_unary_not(child
, side
);
900 filter_free_ir_recursive(child
);
905 case AST_UNARY_BIT_NOT
:
908 goto error_not_supported
;
913 fprintf(stderr
, "[error] %s: unary operation '%s' not supported\n",
919 struct ir_op
*generate_ir_recursive(struct filter_parser_ctx
*ctx
,
920 struct filter_node
*node
, enum ir_side side
)
922 switch (node
->type
) {
925 fprintf(stderr
, "[error] %s: unknown node type\n", __func__
);
930 struct ir_op
*op
, *child
;
932 child
= generate_ir_recursive(ctx
, node
->u
.root
.child
,
936 op
= make_op_root(child
, side
);
938 filter_free_ir_recursive(child
);
943 case NODE_EXPRESSION
:
944 return make_expression(ctx
, node
, side
);
946 return make_op(ctx
, node
, side
);
948 return make_unary_op(ctx
, node
, side
);
954 void filter_ir_free(struct filter_parser_ctx
*ctx
)
956 filter_free_ir_recursive(ctx
->ir_root
);
961 int filter_visitor_ir_generate(struct filter_parser_ctx
*ctx
)
965 op
= generate_ir_recursive(ctx
, &ctx
->ast
->root
, IR_LEFT
);