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"
34 struct ir_op
*generate_ir_recursive(struct filter_parser_ctx
*ctx
,
35 struct filter_node
*node
, enum ir_side side
);
38 struct ir_op
*make_op_root(struct ir_op
*child
, enum ir_side side
)
42 op
= calloc(sizeof(struct ir_op
), 1);
45 switch (child
->data_type
) {
48 fprintf(stderr
, "[error] Unknown root child data type\n");
52 fprintf(stderr
, "[error] String cannot be root data type\n");
56 case IR_DATA_FIELD_REF
:
62 op
->data_type
= child
->data_type
;
63 op
->signedness
= child
->signedness
;
64 op
->u
.root
.child
= child
;
69 struct ir_op
*make_op_load_string(char *string
, enum ir_side side
)
73 op
= calloc(sizeof(struct ir_op
), 1);
77 op
->data_type
= IR_DATA_STRING
;
78 op
->signedness
= IR_SIGN_UNKNOWN
;
80 op
->u
.load
.u
.string
= strdup(string
);
81 if (!op
->u
.load
.u
.string
) {
89 struct ir_op
*make_op_load_numeric(int64_t v
, enum ir_side side
)
93 op
= calloc(sizeof(struct ir_op
), 1);
97 op
->data_type
= IR_DATA_NUMERIC
;
98 /* TODO: for now, all numeric values are signed */
99 op
->signedness
= IR_SIGNED
;
101 op
->u
.load
.u
.num
= v
;
106 struct ir_op
*make_op_load_float(double v
, enum ir_side side
)
110 op
= calloc(sizeof(struct ir_op
), 1);
114 op
->data_type
= IR_DATA_FLOAT
;
115 op
->signedness
= IR_SIGN_UNKNOWN
;
117 op
->u
.load
.u
.flt
= v
;
122 struct ir_op
*make_op_load_field_ref(char *string
, enum ir_side side
)
126 op
= calloc(sizeof(struct ir_op
), 1);
130 op
->data_type
= IR_DATA_FIELD_REF
;
131 op
->signedness
= IR_SIGN_DYN
;
133 op
->u
.load
.u
.ref
= strdup(string
);
134 if (!op
->u
.load
.u
.ref
) {
142 struct ir_op
*make_op_unary(enum unary_op_type unary_op_type
,
143 const char *op_str
, enum ir_op_signedness signedness
,
144 struct ir_op
*child
, enum ir_side side
)
146 struct ir_op
*op
= NULL
;
148 if (child
->data_type
== IR_DATA_STRING
) {
149 fprintf(stderr
, "[error] unary operation '%s' not allowed on string literal\n", op_str
);
153 op
= calloc(sizeof(struct ir_op
), 1);
156 op
->op
= IR_OP_UNARY
;
157 op
->data_type
= child
->data_type
;
158 op
->signedness
= signedness
;
160 op
->u
.unary
.type
= unary_op_type
;
161 op
->u
.unary
.child
= child
;
170 * unary + is pretty much useless.
173 struct ir_op
*make_op_unary_plus(struct ir_op
*child
, enum ir_side side
)
175 return make_op_unary(AST_UNARY_PLUS
, "+", child
->signedness
,
180 struct ir_op
*make_op_unary_minus(struct ir_op
*child
, enum ir_side side
)
182 return make_op_unary(AST_UNARY_MINUS
, "-", child
->signedness
,
187 struct ir_op
*make_op_unary_not(struct ir_op
*child
, enum ir_side side
)
189 return make_op_unary(AST_UNARY_NOT
, "!", child
->signedness
,
195 struct ir_op
*make_op_binary_numeric(enum op_type bin_op_type
,
196 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
199 struct ir_op
*op
= NULL
;
201 if (right
->data_type
== IR_DATA_STRING
202 || right
->data_type
== IR_DATA_STRING
) {
203 fprintf(stderr
, "[error] binary operation '%s' not allowed on string literal\n", op_str
);
206 if (left
->data_type
== IR_DATA_UNKNOWN
207 || right
->data_type
== IR_DATA_UNKNOWN
) {
208 fprintf(stderr
, "[error] binary operation '%s' has unknown type for both children\n", op_str
);
213 op
= calloc(sizeof(struct ir_op_binary
), 1);
216 op
->op
= IR_OP_BINARY
;
217 op
->u
.binary
.type
= bin_op_type
;
218 op
->u
.binary
.left
= left
;
219 op
->u
.binary
.right
= right
;
223 * The field that is not a field ref will select type.
225 if (left
->data_type
!= IR_DATA_FIELD_REF
)
226 op
->data_type
= left
->data_type
;
228 op
->data_type
= right
->data_type
;
230 if (left
->signedness
== IR_SIGNED
231 || right
->signedness
== IR_SIGNED
) {
232 op
->signedness
= IR_SIGNED
;
233 } else if (left
->signedness
== IR_SIGN_DYN
234 || right
->signedness
== IR_SIGN_DYN
) {
235 op
->signedness
= IR_SIGN_DYN
;
236 } else if (left
->signedness
== IR_UNSIGNED
237 && right
->signedness
== IR_UNSIGNED
) {
238 op
->signedness
= IR_UNSIGNED
;
240 op
->signedness
= IR_SIGN_UNKNOWN
;
251 struct ir_op
*make_op_binary_mul(struct ir_op
*left
, struct ir_op
*right
,
254 return make_op_binary_numeric(AST_OP_MUL
, "*", left
, right
, side
);
258 struct ir_op
*make_op_binary_div(struct ir_op
*left
, struct ir_op
*right
,
261 return make_op_binary_numeric(AST_OP_DIV
, "/", left
, right
, side
);
265 struct ir_op
*make_op_binary_mod(struct ir_op
*left
, struct ir_op
*right
,
268 return make_op_binary_numeric(AST_OP_MOD
, "%", left
, right
, side
);
272 struct ir_op
*make_op_binary_plus(struct ir_op
*left
, struct ir_op
*right
,
275 return make_op_binary_numeric(AST_OP_PLUS
, "+", left
, right
, side
);
279 struct ir_op
*make_op_binary_minus(struct ir_op
*left
, struct ir_op
*right
,
282 return make_op_binary_numeric(AST_OP_MINUS
, "-", left
, right
, side
);
286 struct ir_op
*make_op_binary_rshift(struct ir_op
*left
, struct ir_op
*right
,
289 return make_op_binary_numeric(AST_OP_RSHIFT
, ">>", left
, right
, side
);
293 struct ir_op
*make_op_binary_lshift(struct ir_op
*left
, struct ir_op
*right
,
296 return make_op_binary_numeric(AST_OP_LSHIFT
, "<<", left
, right
, side
);
300 struct ir_op
*make_op_binary_and(struct ir_op
*left
, struct ir_op
*right
,
303 return make_op_binary_numeric(AST_OP_BIN_AND
, "&", left
, right
, side
);
307 struct ir_op
*make_op_binary_or(struct ir_op
*left
, struct ir_op
*right
,
310 return make_op_binary_numeric(AST_OP_BIN_OR
, "|", left
, right
, side
);
314 struct ir_op
*make_op_binary_xor(struct ir_op
*left
, struct ir_op
*right
,
317 return make_op_binary_numeric(AST_OP_BIN_XOR
, "^", left
, right
, side
);
322 struct ir_op
*make_op_binary_compare(enum op_type bin_op_type
,
323 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
326 struct ir_op
*op
= NULL
;
328 if (left
->data_type
== IR_DATA_UNKNOWN
329 || right
->data_type
== IR_DATA_UNKNOWN
) {
330 fprintf(stderr
, "[error] binary operation '%s' has unknown operand type\n", op_str
);
334 if ((left
->data_type
== IR_DATA_STRING
335 && (right
->data_type
== IR_DATA_NUMERIC
|| right
->data_type
== IR_DATA_FLOAT
))
336 || ((left
->data_type
== IR_DATA_NUMERIC
|| left
->data_type
== IR_DATA_FLOAT
) &&
337 right
->data_type
== IR_DATA_STRING
)) {
338 fprintf(stderr
, "[error] binary operation '%s' operand type mismatch\n", op_str
);
342 op
= calloc(sizeof(struct ir_op
), 1);
345 op
->op
= IR_OP_BINARY
;
346 op
->u
.binary
.type
= bin_op_type
;
347 op
->u
.binary
.left
= left
;
348 op
->u
.binary
.right
= right
;
350 /* we return a boolean, represented as signed numeric */
351 op
->data_type
= IR_DATA_NUMERIC
;
352 op
->signedness
= IR_SIGNED
;
363 struct ir_op
*make_op_binary_eq(struct ir_op
*left
, struct ir_op
*right
,
366 return make_op_binary_compare(AST_OP_EQ
, "==", left
, right
, side
);
370 struct ir_op
*make_op_binary_ne(struct ir_op
*left
, struct ir_op
*right
,
373 return make_op_binary_compare(AST_OP_NE
, "!=", left
, right
, side
);
377 struct ir_op
*make_op_binary_gt(struct ir_op
*left
, struct ir_op
*right
,
380 return make_op_binary_compare(AST_OP_GT
, ">", left
, right
, side
);
384 struct ir_op
*make_op_binary_lt(struct ir_op
*left
, struct ir_op
*right
,
387 return make_op_binary_compare(AST_OP_LT
, "<", left
, right
, side
);
391 struct ir_op
*make_op_binary_ge(struct ir_op
*left
, struct ir_op
*right
,
394 return make_op_binary_compare(AST_OP_GE
, ">=", left
, right
, side
);
398 struct ir_op
*make_op_binary_le(struct ir_op
*left
, struct ir_op
*right
,
401 return make_op_binary_compare(AST_OP_LE
, "<=", left
, right
, side
);
405 struct ir_op
*make_op_binary_logical(enum op_type bin_op_type
,
406 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
409 struct ir_op
*op
= NULL
;
411 if (left
->data_type
== IR_DATA_UNKNOWN
412 || right
->data_type
== IR_DATA_UNKNOWN
) {
413 fprintf(stderr
, "[error] binary operation '%s' has unknown operand type\n", op_str
);
417 if (left
->data_type
== IR_DATA_STRING
418 || right
->data_type
== IR_DATA_STRING
) {
419 fprintf(stderr
, "[error] logical binary operation '%s' cannot have string operand\n", op_str
);
423 op
= calloc(sizeof(struct ir_op
), 1);
426 op
->op
= IR_OP_LOGICAL
;
427 op
->u
.binary
.type
= bin_op_type
;
428 op
->u
.binary
.left
= left
;
429 op
->u
.binary
.right
= right
;
431 /* we return a boolean, represented as signed numeric */
432 op
->data_type
= IR_DATA_NUMERIC
;
433 op
->signedness
= IR_SIGNED
;
444 struct ir_op
*make_op_binary_logical_and(struct ir_op
*left
, struct ir_op
*right
,
447 return make_op_binary_logical(AST_OP_AND
, "&&", left
, right
, side
);
451 struct ir_op
*make_op_binary_logical_or(struct ir_op
*left
, struct ir_op
*right
,
454 return make_op_binary_logical(AST_OP_OR
, "||", left
, right
, side
);
458 void filter_free_ir_recursive(struct ir_op
*op
)
465 fprintf(stderr
, "[error] Unknown op type in %s\n",
469 filter_free_ir_recursive(op
->u
.root
.child
);
472 switch (op
->data_type
) {
474 free(op
->u
.load
.u
.string
);
476 case IR_DATA_FIELD_REF
:
477 free(op
->u
.load
.u
.ref
);
484 filter_free_ir_recursive(op
->u
.unary
.child
);
487 filter_free_ir_recursive(op
->u
.binary
.left
);
488 filter_free_ir_recursive(op
->u
.binary
.right
);
491 filter_free_ir_recursive(op
->u
.logical
.left
);
492 filter_free_ir_recursive(op
->u
.logical
.right
);
499 struct ir_op
*make_expression(struct filter_parser_ctx
*ctx
,
500 struct filter_node
*node
, enum ir_side side
)
502 switch (node
->u
.expression
.type
) {
503 case AST_EXP_UNKNOWN
:
505 fprintf(stderr
, "[error] %s: unknown expression type\n", __func__
);
509 return make_op_load_string(node
->u
.expression
.u
.string
, side
);
510 case AST_EXP_CONSTANT
:
511 return make_op_load_numeric(node
->u
.expression
.u
.constant
,
513 case AST_EXP_FLOAT_CONSTANT
:
514 return make_op_load_float(node
->u
.expression
.u
.float_constant
,
516 case AST_EXP_IDENTIFIER
:
517 if (node
->u
.expression
.pre_op
!= AST_LINK_UNKNOWN
) {
518 fprintf(stderr
, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__
);
521 return make_op_load_field_ref(node
->u
.expression
.u
.identifier
,
524 return generate_ir_recursive(ctx
, node
->u
.expression
.u
.child
,
530 struct ir_op
*make_op(struct filter_parser_ctx
*ctx
,
531 struct filter_node
*node
, enum ir_side side
)
533 struct ir_op
*op
= NULL
, *lchild
, *rchild
;
534 const char *op_str
= "?";
536 switch (node
->u
.op
.type
) {
539 fprintf(stderr
, "[error] %s: unknown binary op type\n", __func__
);
543 * Binary operators other than comparators and logical and/or
544 * are not supported. If we ever want to support those, we will
545 * need a stack for the general case rather than just 2
546 * registers (see bytecode).
550 goto error_not_supported
;
553 goto error_not_supported
;
556 goto error_not_supported
;
559 goto error_not_supported
;
562 goto error_not_supported
;
565 goto error_not_supported
;
568 goto error_not_supported
;
571 goto error_not_supported
;
574 goto error_not_supported
;
577 goto error_not_supported
;
585 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
588 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_RIGHT
);
590 filter_free_ir_recursive(lchild
);
598 * Both children considered as left, since we need to
601 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
604 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_LEFT
);
606 filter_free_ir_recursive(lchild
);
612 switch (node
->u
.op
.type
) {
614 op
= make_op_binary_logical_and(lchild
, rchild
, side
);
617 op
= make_op_binary_logical_or(lchild
, rchild
, side
);
620 op
= make_op_binary_eq(lchild
, rchild
, side
);
623 op
= make_op_binary_ne(lchild
, rchild
, side
);
626 op
= make_op_binary_gt(lchild
, rchild
, side
);
629 op
= make_op_binary_lt(lchild
, rchild
, side
);
632 op
= make_op_binary_ge(lchild
, rchild
, side
);
635 op
= make_op_binary_le(lchild
, rchild
, side
);
642 filter_free_ir_recursive(rchild
);
643 filter_free_ir_recursive(lchild
);
648 fprintf(stderr
, "[error] %s: binary operation '%s' not supported\n",
654 struct ir_op
*make_unary_op(struct filter_parser_ctx
*ctx
,
655 struct filter_node
*node
, enum ir_side side
)
657 const char *op_str
= "?";
659 switch (node
->u
.unary_op
.type
) {
660 case AST_UNARY_UNKNOWN
:
662 fprintf(stderr
, "[error] %s: unknown unary op type\n", __func__
);
667 struct ir_op
*op
, *child
;
669 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
673 op
= make_op_unary_plus(child
, side
);
675 filter_free_ir_recursive(child
);
680 case AST_UNARY_MINUS
:
682 struct ir_op
*op
, *child
;
684 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
688 op
= make_op_unary_minus(child
, side
);
690 filter_free_ir_recursive(child
);
697 struct ir_op
*op
, *child
;
699 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
703 op
= make_op_unary_not(child
, side
);
705 filter_free_ir_recursive(child
);
710 case AST_UNARY_BIN_NOT
:
713 goto error_not_supported
;
718 fprintf(stderr
, "[error] %s: unary operation '%s' not supported\n",
724 struct ir_op
*generate_ir_recursive(struct filter_parser_ctx
*ctx
,
725 struct filter_node
*node
, enum ir_side side
)
727 switch (node
->type
) {
730 fprintf(stderr
, "[error] %s: unknown node type\n", __func__
);
735 struct ir_op
*op
, *child
;
737 child
= generate_ir_recursive(ctx
, node
->u
.root
.child
,
741 op
= make_op_root(child
, side
);
743 filter_free_ir_recursive(child
);
748 case NODE_EXPRESSION
:
749 return make_expression(ctx
, node
, side
);
751 return make_op(ctx
, node
, side
);
753 return make_unary_op(ctx
, node
, side
);
758 __attribute__((visibility("hidden")))
759 void filter_ir_free(struct filter_parser_ctx
*ctx
)
761 filter_free_ir_recursive(ctx
->ir_root
);
765 __attribute__((visibility("hidden")))
766 int filter_visitor_ir_generate(struct filter_parser_ctx
*ctx
)
770 op
= generate_ir_recursive(ctx
, &ctx
->ast
->root
, IR_LEFT
);