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>
36 struct ir_op
*generate_ir_recursive(struct filter_parser_ctx
*ctx
,
37 struct filter_node
*node
, enum ir_side side
);
40 struct ir_op
*make_op_root(struct ir_op
*child
, enum ir_side side
)
44 op
= calloc(sizeof(struct ir_op
), 1);
47 switch (child
->data_type
) {
50 fprintf(stderr
, "[error] Unknown root child data type\n");
54 fprintf(stderr
, "[error] String cannot be root data type\n");
58 case IR_DATA_FIELD_REF
:
64 op
->data_type
= child
->data_type
;
65 op
->signedness
= child
->signedness
;
66 op
->u
.root
.child
= child
;
71 struct ir_op
*make_op_load_string(char *string
, enum ir_side side
)
75 op
= calloc(sizeof(struct ir_op
), 1);
79 op
->data_type
= IR_DATA_STRING
;
80 op
->signedness
= IR_SIGN_UNKNOWN
;
82 op
->u
.load
.u
.string
= strdup(string
);
83 if (!op
->u
.load
.u
.string
) {
91 struct ir_op
*make_op_load_numeric(int64_t v
, enum ir_side side
)
95 op
= calloc(sizeof(struct ir_op
), 1);
99 op
->data_type
= IR_DATA_NUMERIC
;
100 /* TODO: for now, all numeric values are signed */
101 op
->signedness
= IR_SIGNED
;
103 op
->u
.load
.u
.num
= v
;
108 struct ir_op
*make_op_load_float(double v
, enum ir_side side
)
112 op
= calloc(sizeof(struct ir_op
), 1);
116 op
->data_type
= IR_DATA_FLOAT
;
117 op
->signedness
= IR_SIGN_UNKNOWN
;
119 op
->u
.load
.u
.flt
= v
;
124 struct ir_op
*make_op_load_field_ref(char *string
, enum ir_side side
)
128 op
= calloc(sizeof(struct ir_op
), 1);
132 op
->data_type
= IR_DATA_FIELD_REF
;
133 op
->signedness
= IR_SIGN_DYN
;
135 op
->u
.load
.u
.ref
= strdup(string
);
136 if (!op
->u
.load
.u
.ref
) {
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
)
148 struct ir_op
*op
= NULL
;
150 if (child
->data_type
== IR_DATA_STRING
) {
151 fprintf(stderr
, "[error] unary operation '%s' not allowed on string literal\n", op_str
);
155 op
= calloc(sizeof(struct ir_op
), 1);
158 op
->op
= IR_OP_UNARY
;
159 op
->data_type
= child
->data_type
;
160 op
->signedness
= signedness
;
162 op
->u
.unary
.type
= unary_op_type
;
163 op
->u
.unary
.child
= child
;
172 * unary + is pretty much useless.
175 struct ir_op
*make_op_unary_plus(struct ir_op
*child
, enum ir_side side
)
177 return make_op_unary(AST_UNARY_PLUS
, "+", child
->signedness
,
182 struct ir_op
*make_op_unary_minus(struct ir_op
*child
, enum ir_side side
)
184 return make_op_unary(AST_UNARY_MINUS
, "-", child
->signedness
,
189 struct ir_op
*make_op_unary_not(struct ir_op
*child
, enum ir_side side
)
191 return make_op_unary(AST_UNARY_NOT
, "!", child
->signedness
,
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
,
201 struct ir_op
*op
= NULL
;
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
);
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
);
215 op
= calloc(sizeof(struct ir_op_binary
), 1);
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
;
225 * The field that is not a field ref will select type.
227 if (left
->data_type
!= IR_DATA_FIELD_REF
)
228 op
->data_type
= left
->data_type
;
230 op
->data_type
= right
->data_type
;
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
;
242 op
->signedness
= IR_SIGN_UNKNOWN
;
253 struct ir_op
*make_op_binary_mul(struct ir_op
*left
, struct ir_op
*right
,
256 return make_op_binary_numeric(AST_OP_MUL
, "*", left
, right
, side
);
260 struct ir_op
*make_op_binary_div(struct ir_op
*left
, struct ir_op
*right
,
263 return make_op_binary_numeric(AST_OP_DIV
, "/", left
, right
, side
);
267 struct ir_op
*make_op_binary_mod(struct ir_op
*left
, struct ir_op
*right
,
270 return make_op_binary_numeric(AST_OP_MOD
, "%", left
, right
, side
);
274 struct ir_op
*make_op_binary_plus(struct ir_op
*left
, struct ir_op
*right
,
277 return make_op_binary_numeric(AST_OP_PLUS
, "+", left
, right
, side
);
281 struct ir_op
*make_op_binary_minus(struct ir_op
*left
, struct ir_op
*right
,
284 return make_op_binary_numeric(AST_OP_MINUS
, "-", left
, right
, side
);
288 struct ir_op
*make_op_binary_rshift(struct ir_op
*left
, struct ir_op
*right
,
291 return make_op_binary_numeric(AST_OP_RSHIFT
, ">>", left
, right
, side
);
295 struct ir_op
*make_op_binary_lshift(struct ir_op
*left
, struct ir_op
*right
,
298 return make_op_binary_numeric(AST_OP_LSHIFT
, "<<", left
, right
, side
);
302 struct ir_op
*make_op_binary_and(struct ir_op
*left
, struct ir_op
*right
,
305 return make_op_binary_numeric(AST_OP_BIN_AND
, "&", left
, right
, side
);
309 struct ir_op
*make_op_binary_or(struct ir_op
*left
, struct ir_op
*right
,
312 return make_op_binary_numeric(AST_OP_BIN_OR
, "|", left
, right
, side
);
316 struct ir_op
*make_op_binary_xor(struct ir_op
*left
, struct ir_op
*right
,
319 return make_op_binary_numeric(AST_OP_BIN_XOR
, "^", left
, right
, side
);
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
,
328 struct ir_op
*op
= NULL
;
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
);
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
);
344 op
= calloc(sizeof(struct ir_op
), 1);
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
;
352 /* we return a boolean, represented as signed numeric */
353 op
->data_type
= IR_DATA_NUMERIC
;
354 op
->signedness
= IR_SIGNED
;
365 struct ir_op
*make_op_binary_eq(struct ir_op
*left
, struct ir_op
*right
,
368 return make_op_binary_compare(AST_OP_EQ
, "==", left
, right
, side
);
372 struct ir_op
*make_op_binary_ne(struct ir_op
*left
, struct ir_op
*right
,
375 return make_op_binary_compare(AST_OP_NE
, "!=", left
, right
, side
);
379 struct ir_op
*make_op_binary_gt(struct ir_op
*left
, struct ir_op
*right
,
382 return make_op_binary_compare(AST_OP_GT
, ">", left
, right
, side
);
386 struct ir_op
*make_op_binary_lt(struct ir_op
*left
, struct ir_op
*right
,
389 return make_op_binary_compare(AST_OP_LT
, "<", left
, right
, side
);
393 struct ir_op
*make_op_binary_ge(struct ir_op
*left
, struct ir_op
*right
,
396 return make_op_binary_compare(AST_OP_GE
, ">=", left
, right
, side
);
400 struct ir_op
*make_op_binary_le(struct ir_op
*left
, struct ir_op
*right
,
403 return make_op_binary_compare(AST_OP_LE
, "<=", left
, right
, side
);
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
,
411 struct ir_op
*op
= NULL
;
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
);
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
);
425 op
= calloc(sizeof(struct ir_op
), 1);
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
;
433 /* we return a boolean, represented as signed numeric */
434 op
->data_type
= IR_DATA_NUMERIC
;
435 op
->signedness
= IR_SIGNED
;
446 struct ir_op
*make_op_binary_logical_and(struct ir_op
*left
, struct ir_op
*right
,
449 return make_op_binary_logical(AST_OP_AND
, "&&", left
, right
, side
);
453 struct ir_op
*make_op_binary_logical_or(struct ir_op
*left
, struct ir_op
*right
,
456 return make_op_binary_logical(AST_OP_OR
, "||", left
, right
, side
);
460 void filter_free_ir_recursive(struct ir_op
*op
)
467 fprintf(stderr
, "[error] Unknown op type in %s\n",
471 filter_free_ir_recursive(op
->u
.root
.child
);
474 switch (op
->data_type
) {
476 free(op
->u
.load
.u
.string
);
478 case IR_DATA_FIELD_REF
:
479 free(op
->u
.load
.u
.ref
);
486 filter_free_ir_recursive(op
->u
.unary
.child
);
489 filter_free_ir_recursive(op
->u
.binary
.left
);
490 filter_free_ir_recursive(op
->u
.binary
.right
);
493 filter_free_ir_recursive(op
->u
.logical
.left
);
494 filter_free_ir_recursive(op
->u
.logical
.right
);
501 struct ir_op
*make_expression(struct filter_parser_ctx
*ctx
,
502 struct filter_node
*node
, enum ir_side side
)
504 switch (node
->u
.expression
.type
) {
505 case AST_EXP_UNKNOWN
:
507 fprintf(stderr
, "[error] %s: unknown expression type\n", __func__
);
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
,
515 case AST_EXP_FLOAT_CONSTANT
:
516 return make_op_load_float(node
->u
.expression
.u
.float_constant
,
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__
);
523 return make_op_load_field_ref(node
->u
.expression
.u
.identifier
,
526 return generate_ir_recursive(ctx
, node
->u
.expression
.u
.child
,
532 struct ir_op
*make_op(struct filter_parser_ctx
*ctx
,
533 struct filter_node
*node
, enum ir_side side
)
535 struct ir_op
*op
= NULL
, *lchild
, *rchild
;
536 const char *op_str
= "?";
538 switch (node
->u
.op
.type
) {
541 fprintf(stderr
, "[error] %s: unknown binary op type\n", __func__
);
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).
552 goto error_not_supported
;
555 goto error_not_supported
;
558 goto error_not_supported
;
561 goto error_not_supported
;
564 goto error_not_supported
;
567 goto error_not_supported
;
570 goto error_not_supported
;
573 goto error_not_supported
;
576 goto error_not_supported
;
579 goto error_not_supported
;
587 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
590 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_RIGHT
);
592 filter_free_ir_recursive(lchild
);
600 * Both children considered as left, since we need to
603 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
606 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_LEFT
);
608 filter_free_ir_recursive(lchild
);
614 switch (node
->u
.op
.type
) {
616 op
= make_op_binary_logical_and(lchild
, rchild
, side
);
619 op
= make_op_binary_logical_or(lchild
, rchild
, side
);
622 op
= make_op_binary_eq(lchild
, rchild
, side
);
625 op
= make_op_binary_ne(lchild
, rchild
, side
);
628 op
= make_op_binary_gt(lchild
, rchild
, side
);
631 op
= make_op_binary_lt(lchild
, rchild
, side
);
634 op
= make_op_binary_ge(lchild
, rchild
, side
);
637 op
= make_op_binary_le(lchild
, rchild
, side
);
644 filter_free_ir_recursive(rchild
);
645 filter_free_ir_recursive(lchild
);
650 fprintf(stderr
, "[error] %s: binary operation '%s' not supported\n",
656 struct ir_op
*make_unary_op(struct filter_parser_ctx
*ctx
,
657 struct filter_node
*node
, enum ir_side side
)
659 const char *op_str
= "?";
661 switch (node
->u
.unary_op
.type
) {
662 case AST_UNARY_UNKNOWN
:
664 fprintf(stderr
, "[error] %s: unknown unary op type\n", __func__
);
669 struct ir_op
*op
, *child
;
671 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
675 op
= make_op_unary_plus(child
, side
);
677 filter_free_ir_recursive(child
);
682 case AST_UNARY_MINUS
:
684 struct ir_op
*op
, *child
;
686 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
690 op
= make_op_unary_minus(child
, side
);
692 filter_free_ir_recursive(child
);
699 struct ir_op
*op
, *child
;
701 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
705 op
= make_op_unary_not(child
, side
);
707 filter_free_ir_recursive(child
);
712 case AST_UNARY_BIN_NOT
:
715 goto error_not_supported
;
720 fprintf(stderr
, "[error] %s: unary operation '%s' not supported\n",
726 struct ir_op
*generate_ir_recursive(struct filter_parser_ctx
*ctx
,
727 struct filter_node
*node
, enum ir_side side
)
729 switch (node
->type
) {
732 fprintf(stderr
, "[error] %s: unknown node type\n", __func__
);
737 struct ir_op
*op
, *child
;
739 child
= generate_ir_recursive(ctx
, node
->u
.root
.child
,
743 op
= make_op_root(child
, side
);
745 filter_free_ir_recursive(child
);
750 case NODE_EXPRESSION
:
751 return make_expression(ctx
, node
, side
);
753 return make_op(ctx
, node
, side
);
755 return make_unary_op(ctx
, node
, side
);
761 void filter_ir_free(struct filter_parser_ctx
*ctx
)
763 filter_free_ir_recursive(ctx
->ir_root
);
768 int filter_visitor_ir_generate(struct filter_parser_ctx
*ctx
)
772 op
= generate_ir_recursive(ctx
, &ctx
->ast
->root
, IR_LEFT
);