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");
51 fprintf(stderr
, "[error] String cannot be root data type\n");
54 case IR_DATA_FIELD_REF
:
60 op
->data_type
= child
->data_type
;
61 op
->signedness
= child
->signedness
;
62 op
->u
.root
.child
= child
;
67 struct ir_op
*make_op_load_string(char *string
, enum ir_side side
)
71 op
= calloc(sizeof(struct ir_op
), 1);
75 op
->data_type
= IR_DATA_STRING
;
76 op
->signedness
= IR_SIGN_UNKNOWN
;
78 op
->u
.load
.u
.string
= strdup(string
);
79 if (!op
->u
.load
.u
.string
) {
87 struct ir_op
*make_op_load_numeric(int64_t v
, enum ir_side side
)
91 op
= calloc(sizeof(struct ir_op
), 1);
95 op
->data_type
= IR_DATA_NUMERIC
;
96 /* TODO: for now, all numeric values are signed */
97 op
->signedness
= IR_SIGNED
;
104 struct ir_op
*make_op_load_float(double v
, enum ir_side side
)
108 op
= calloc(sizeof(struct ir_op
), 1);
112 op
->data_type
= IR_DATA_FLOAT
;
113 op
->signedness
= IR_SIGN_UNKNOWN
;
115 op
->u
.load
.u
.flt
= v
;
120 struct ir_op
*make_op_load_field_ref(char *string
, enum ir_side side
)
124 op
= calloc(sizeof(struct ir_op
), 1);
128 op
->data_type
= IR_DATA_FIELD_REF
;
129 op
->signedness
= IR_SIGN_DYN
;
131 op
->u
.load
.u
.ref
= strdup(string
);
132 if (!op
->u
.load
.u
.ref
) {
140 struct ir_op
*make_op_unary(enum unary_op_type unary_op_type
,
141 const char *op_str
, enum ir_op_signedness signedness
,
142 struct ir_op
*child
, enum ir_side side
)
144 struct ir_op
*op
= NULL
;
146 if (child
->data_type
== IR_DATA_STRING
) {
147 fprintf(stderr
, "[error] unary operation '%s' not allowed on string literal\n", op_str
);
151 op
= calloc(sizeof(struct ir_op
), 1);
154 op
->op
= IR_OP_UNARY
;
155 op
->data_type
= child
->data_type
;
156 op
->signedness
= signedness
;
158 op
->u
.unary
.type
= unary_op_type
;
159 op
->u
.unary
.child
= child
;
168 * unary + is pretty much useless.
171 struct ir_op
*make_op_unary_plus(struct ir_op
*child
, enum ir_side side
)
173 return make_op_unary(AST_UNARY_PLUS
, "+", child
->signedness
,
178 struct ir_op
*make_op_unary_minus(struct ir_op
*child
, enum ir_side side
)
180 return make_op_unary(AST_UNARY_MINUS
, "-", child
->signedness
,
185 struct ir_op
*make_op_unary_not(struct ir_op
*child
, enum ir_side side
)
187 return make_op_unary(AST_UNARY_NOT
, "!", child
->signedness
,
193 struct ir_op
*make_op_binary_numeric(enum op_type bin_op_type
,
194 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
197 struct ir_op
*op
= NULL
;
199 if (right
->data_type
== IR_DATA_STRING
200 || right
->data_type
== IR_DATA_STRING
) {
201 fprintf(stderr
, "[error] binary operation '%s' not allowed on string literal\n", op_str
);
204 if (left
->data_type
== IR_DATA_UNKNOWN
205 || right
->data_type
== IR_DATA_UNKNOWN
) {
206 fprintf(stderr
, "[error] binary operation '%s' has unknown type for both children\n", op_str
);
211 op
= calloc(sizeof(struct ir_op_binary
), 1);
214 op
->op
= IR_OP_BINARY
;
215 op
->u
.binary
.type
= bin_op_type
;
216 op
->u
.binary
.left
= left
;
217 op
->u
.binary
.right
= right
;
221 * The field that is not a field ref will select type.
223 if (left
->data_type
!= IR_DATA_FIELD_REF
)
224 op
->data_type
= left
->data_type
;
226 op
->data_type
= right
->data_type
;
228 if (left
->signedness
== IR_SIGNED
229 || right
->signedness
== IR_SIGNED
) {
230 op
->signedness
= IR_SIGNED
;
231 } else if (left
->signedness
== IR_SIGN_DYN
232 || right
->signedness
== IR_SIGN_DYN
) {
233 op
->signedness
= IR_SIGN_DYN
;
234 } else if (left
->signedness
== IR_UNSIGNED
235 && right
->signedness
== IR_UNSIGNED
) {
236 op
->signedness
= IR_UNSIGNED
;
238 op
->signedness
= IR_SIGN_UNKNOWN
;
249 struct ir_op
*make_op_binary_mul(struct ir_op
*left
, struct ir_op
*right
,
252 return make_op_binary_numeric(AST_OP_MUL
, "*", left
, right
, side
);
256 struct ir_op
*make_op_binary_div(struct ir_op
*left
, struct ir_op
*right
,
259 return make_op_binary_numeric(AST_OP_DIV
, "/", left
, right
, side
);
263 struct ir_op
*make_op_binary_mod(struct ir_op
*left
, struct ir_op
*right
,
266 return make_op_binary_numeric(AST_OP_MOD
, "%", left
, right
, side
);
270 struct ir_op
*make_op_binary_plus(struct ir_op
*left
, struct ir_op
*right
,
273 return make_op_binary_numeric(AST_OP_PLUS
, "+", left
, right
, side
);
277 struct ir_op
*make_op_binary_minus(struct ir_op
*left
, struct ir_op
*right
,
280 return make_op_binary_numeric(AST_OP_MINUS
, "-", left
, right
, side
);
284 struct ir_op
*make_op_binary_rshift(struct ir_op
*left
, struct ir_op
*right
,
287 return make_op_binary_numeric(AST_OP_RSHIFT
, ">>", left
, right
, side
);
291 struct ir_op
*make_op_binary_lshift(struct ir_op
*left
, struct ir_op
*right
,
294 return make_op_binary_numeric(AST_OP_LSHIFT
, "<<", left
, right
, side
);
298 struct ir_op
*make_op_binary_and(struct ir_op
*left
, struct ir_op
*right
,
301 return make_op_binary_numeric(AST_OP_BIN_AND
, "&", left
, right
, side
);
305 struct ir_op
*make_op_binary_or(struct ir_op
*left
, struct ir_op
*right
,
308 return make_op_binary_numeric(AST_OP_BIN_OR
, "|", left
, right
, side
);
312 struct ir_op
*make_op_binary_xor(struct ir_op
*left
, struct ir_op
*right
,
315 return make_op_binary_numeric(AST_OP_BIN_XOR
, "^", left
, right
, side
);
320 struct ir_op
*make_op_binary_compare(enum op_type bin_op_type
,
321 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
324 struct ir_op
*op
= NULL
;
326 if (left
->data_type
== IR_DATA_UNKNOWN
327 || right
->data_type
== IR_DATA_UNKNOWN
) {
328 fprintf(stderr
, "[error] binary operation '%s' has unknown operand type\n", op_str
);
332 if ((left
->data_type
== IR_DATA_STRING
333 && (right
->data_type
== IR_DATA_NUMERIC
|| right
->data_type
== IR_DATA_FLOAT
))
334 || ((left
->data_type
== IR_DATA_NUMERIC
|| left
->data_type
== IR_DATA_FLOAT
) &&
335 right
->data_type
== IR_DATA_STRING
)) {
336 fprintf(stderr
, "[error] binary operation '%s' operand type mismatch\n", op_str
);
340 op
= calloc(sizeof(struct ir_op
), 1);
343 op
->op
= IR_OP_BINARY
;
344 op
->u
.binary
.type
= bin_op_type
;
345 op
->u
.binary
.left
= left
;
346 op
->u
.binary
.right
= right
;
348 /* we return a boolean, represented as signed numeric */
349 op
->data_type
= IR_DATA_NUMERIC
;
350 op
->signedness
= IR_SIGNED
;
361 struct ir_op
*make_op_binary_eq(struct ir_op
*left
, struct ir_op
*right
,
364 return make_op_binary_compare(AST_OP_EQ
, "==", left
, right
, side
);
368 struct ir_op
*make_op_binary_ne(struct ir_op
*left
, struct ir_op
*right
,
371 return make_op_binary_compare(AST_OP_NE
, "!=", left
, right
, side
);
375 struct ir_op
*make_op_binary_gt(struct ir_op
*left
, struct ir_op
*right
,
378 return make_op_binary_compare(AST_OP_GT
, ">", left
, right
, side
);
382 struct ir_op
*make_op_binary_lt(struct ir_op
*left
, struct ir_op
*right
,
385 return make_op_binary_compare(AST_OP_LT
, "<", left
, right
, side
);
389 struct ir_op
*make_op_binary_ge(struct ir_op
*left
, struct ir_op
*right
,
392 return make_op_binary_compare(AST_OP_GE
, ">=", left
, right
, side
);
396 struct ir_op
*make_op_binary_le(struct ir_op
*left
, struct ir_op
*right
,
399 return make_op_binary_compare(AST_OP_LE
, "<=", left
, right
, side
);
403 struct ir_op
*make_op_binary_logical(enum op_type bin_op_type
,
404 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
407 struct ir_op
*op
= NULL
;
409 if (left
->data_type
== IR_DATA_UNKNOWN
410 || right
->data_type
== IR_DATA_UNKNOWN
) {
411 fprintf(stderr
, "[error] binary operation '%s' has unknown operand type\n", op_str
);
415 if (left
->data_type
== IR_DATA_STRING
416 || right
->data_type
== IR_DATA_STRING
) {
417 fprintf(stderr
, "[error] logical binary operation '%s' cannot have string operand\n", op_str
);
421 op
= calloc(sizeof(struct ir_op
), 1);
424 op
->op
= IR_OP_LOGICAL
;
425 op
->u
.binary
.type
= bin_op_type
;
426 op
->u
.binary
.left
= left
;
427 op
->u
.binary
.right
= right
;
429 /* we return a boolean, represented as signed numeric */
430 op
->data_type
= IR_DATA_NUMERIC
;
431 op
->signedness
= IR_SIGNED
;
442 struct ir_op
*make_op_binary_logical_and(struct ir_op
*left
, struct ir_op
*right
,
445 return make_op_binary_logical(AST_OP_AND
, "&&", left
, right
, side
);
449 struct ir_op
*make_op_binary_logical_or(struct ir_op
*left
, struct ir_op
*right
,
452 return make_op_binary_logical(AST_OP_OR
, "||", left
, right
, side
);
456 void filter_free_ir_recursive(struct ir_op
*op
)
463 fprintf(stderr
, "[error] Unknown op type in %s\n",
467 filter_free_ir_recursive(op
->u
.root
.child
);
470 switch (op
->data_type
) {
472 free(op
->u
.load
.u
.string
);
474 case IR_DATA_FIELD_REF
:
475 free(op
->u
.load
.u
.ref
);
482 filter_free_ir_recursive(op
->u
.unary
.child
);
485 filter_free_ir_recursive(op
->u
.binary
.left
);
486 filter_free_ir_recursive(op
->u
.binary
.right
);
489 filter_free_ir_recursive(op
->u
.logical
.left
);
490 filter_free_ir_recursive(op
->u
.logical
.right
);
497 struct ir_op
*make_expression(struct filter_parser_ctx
*ctx
,
498 struct filter_node
*node
, enum ir_side side
)
500 switch (node
->u
.expression
.type
) {
501 case AST_EXP_UNKNOWN
:
503 fprintf(stderr
, "[error] %s: unknown expression type\n", __func__
);
507 return make_op_load_string(node
->u
.expression
.u
.string
, side
);
508 case AST_EXP_CONSTANT
:
509 return make_op_load_numeric(node
->u
.expression
.u
.constant
,
511 case AST_EXP_FLOAT_CONSTANT
:
512 return make_op_load_float(node
->u
.expression
.u
.float_constant
,
514 case AST_EXP_IDENTIFIER
:
515 if (node
->u
.expression
.pre_op
!= AST_LINK_UNKNOWN
) {
516 fprintf(stderr
, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__
);
519 return make_op_load_field_ref(node
->u
.expression
.u
.identifier
,
522 return generate_ir_recursive(ctx
, node
->u
.expression
.u
.child
,
528 struct ir_op
*make_op(struct filter_parser_ctx
*ctx
,
529 struct filter_node
*node
, enum ir_side side
)
531 struct ir_op
*op
= NULL
, *lchild
, *rchild
;
532 const char *op_str
= "?";
534 switch (node
->u
.op
.type
) {
537 fprintf(stderr
, "[error] %s: unknown binary op type\n", __func__
);
541 * Binary operators other than comparators and logical and/or
542 * are not supported. If we ever want to support those, we will
543 * need a stack for the general case rather than just 2
544 * registers (see bytecode).
548 goto error_not_supported
;
551 goto error_not_supported
;
554 goto error_not_supported
;
557 goto error_not_supported
;
560 goto error_not_supported
;
563 goto error_not_supported
;
566 goto error_not_supported
;
569 goto error_not_supported
;
572 goto error_not_supported
;
575 goto error_not_supported
;
583 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
586 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_RIGHT
);
588 filter_free_ir_recursive(lchild
);
596 * Both children considered as left, since we need to
599 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
602 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_LEFT
);
604 filter_free_ir_recursive(lchild
);
610 switch (node
->u
.op
.type
) {
612 op
= make_op_binary_logical_and(lchild
, rchild
, side
);
615 op
= make_op_binary_logical_or(lchild
, rchild
, side
);
618 op
= make_op_binary_eq(lchild
, rchild
, side
);
621 op
= make_op_binary_ne(lchild
, rchild
, side
);
624 op
= make_op_binary_gt(lchild
, rchild
, side
);
627 op
= make_op_binary_lt(lchild
, rchild
, side
);
630 op
= make_op_binary_ge(lchild
, rchild
, side
);
633 op
= make_op_binary_le(lchild
, rchild
, side
);
640 filter_free_ir_recursive(rchild
);
641 filter_free_ir_recursive(lchild
);
646 fprintf(stderr
, "[error] %s: binary operation '%s' not supported\n",
652 struct ir_op
*make_unary_op(struct filter_parser_ctx
*ctx
,
653 struct filter_node
*node
, enum ir_side side
)
655 switch (node
->u
.unary_op
.type
) {
656 case AST_UNARY_UNKNOWN
:
658 fprintf(stderr
, "[error] %s: unknown unary op type\n", __func__
);
663 struct ir_op
*op
, *child
;
665 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
669 op
= make_op_unary_plus(child
, side
);
671 filter_free_ir_recursive(child
);
676 case AST_UNARY_MINUS
:
678 struct ir_op
*op
, *child
;
680 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
684 op
= make_op_unary_minus(child
, side
);
686 filter_free_ir_recursive(child
);
693 struct ir_op
*op
, *child
;
695 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
699 op
= make_op_unary_not(child
, side
);
701 filter_free_ir_recursive(child
);
710 struct ir_op
*generate_ir_recursive(struct filter_parser_ctx
*ctx
,
711 struct filter_node
*node
, enum ir_side side
)
713 switch (node
->type
) {
716 fprintf(stderr
, "[error] %s: unknown node type\n", __func__
);
721 struct ir_op
*op
, *child
;
723 child
= generate_ir_recursive(ctx
, node
->u
.root
.child
,
727 op
= make_op_root(child
, side
);
729 filter_free_ir_recursive(child
);
734 case NODE_EXPRESSION
:
735 return make_expression(ctx
, node
, side
);
737 return make_op(ctx
, node
, side
);
739 return make_unary_op(ctx
, node
, side
);
745 void filter_ir_free(struct filter_parser_ctx
*ctx
)
747 filter_free_ir_recursive(ctx
->ir_root
);
751 int filter_visitor_ir_generate(struct filter_parser_ctx
*ctx
)
755 op
= generate_ir_recursive(ctx
, &ctx
->ast
->root
, IR_LEFT
);