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
:
59 case IR_DATA_GET_CONTEXT_REF
:
65 op
->data_type
= child
->data_type
;
66 op
->signedness
= child
->signedness
;
67 op
->u
.root
.child
= child
;
72 struct ir_op
*make_op_load_string(char *string
, enum ir_side side
)
76 op
= calloc(sizeof(struct ir_op
), 1);
80 op
->data_type
= IR_DATA_STRING
;
81 op
->signedness
= IR_SIGN_UNKNOWN
;
83 op
->u
.load
.u
.string
= strdup(string
);
84 if (!op
->u
.load
.u
.string
) {
92 struct ir_op
*make_op_load_numeric(int64_t v
, enum ir_side side
)
96 op
= calloc(sizeof(struct ir_op
), 1);
100 op
->data_type
= IR_DATA_NUMERIC
;
101 /* TODO: for now, all numeric values are signed */
102 op
->signedness
= IR_SIGNED
;
104 op
->u
.load
.u
.num
= v
;
109 struct ir_op
*make_op_load_float(double v
, enum ir_side side
)
113 op
= calloc(sizeof(struct ir_op
), 1);
117 op
->data_type
= IR_DATA_FLOAT
;
118 op
->signedness
= IR_SIGN_UNKNOWN
;
120 op
->u
.load
.u
.flt
= v
;
125 struct ir_op
*make_op_load_field_ref(char *string
, enum ir_side side
)
129 op
= calloc(sizeof(struct ir_op
), 1);
133 op
->data_type
= IR_DATA_FIELD_REF
;
134 op
->signedness
= IR_SIGN_DYN
;
136 op
->u
.load
.u
.ref
= strdup(string
);
137 if (!op
->u
.load
.u
.ref
) {
145 struct ir_op
*make_op_load_get_context_ref(char *string
, enum ir_side side
)
149 op
= calloc(sizeof(struct ir_op
), 1);
153 op
->data_type
= IR_DATA_GET_CONTEXT_REF
;
154 op
->signedness
= IR_SIGN_DYN
;
156 op
->u
.load
.u
.ref
= strdup(string
);
157 if (!op
->u
.load
.u
.ref
) {
165 struct ir_op
*make_op_unary(enum unary_op_type unary_op_type
,
166 const char *op_str
, enum ir_op_signedness signedness
,
167 struct ir_op
*child
, enum ir_side side
)
169 struct ir_op
*op
= NULL
;
171 if (child
->data_type
== IR_DATA_STRING
) {
172 fprintf(stderr
, "[error] unary operation '%s' not allowed on string literal\n", op_str
);
176 op
= calloc(sizeof(struct ir_op
), 1);
179 op
->op
= IR_OP_UNARY
;
180 op
->data_type
= child
->data_type
;
181 op
->signedness
= signedness
;
183 op
->u
.unary
.type
= unary_op_type
;
184 op
->u
.unary
.child
= child
;
193 * unary + is pretty much useless.
196 struct ir_op
*make_op_unary_plus(struct ir_op
*child
, enum ir_side side
)
198 return make_op_unary(AST_UNARY_PLUS
, "+", child
->signedness
,
203 struct ir_op
*make_op_unary_minus(struct ir_op
*child
, enum ir_side side
)
205 return make_op_unary(AST_UNARY_MINUS
, "-", child
->signedness
,
210 struct ir_op
*make_op_unary_not(struct ir_op
*child
, enum ir_side side
)
212 return make_op_unary(AST_UNARY_NOT
, "!", child
->signedness
,
217 struct ir_op
*make_op_binary_compare(enum op_type bin_op_type
,
218 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
221 struct ir_op
*op
= NULL
;
223 if (left
->data_type
== IR_DATA_UNKNOWN
224 || right
->data_type
== IR_DATA_UNKNOWN
) {
225 fprintf(stderr
, "[error] binary operation '%s' has unknown operand type\n", op_str
);
229 if ((left
->data_type
== IR_DATA_STRING
230 && (right
->data_type
== IR_DATA_NUMERIC
|| right
->data_type
== IR_DATA_FLOAT
))
231 || ((left
->data_type
== IR_DATA_NUMERIC
|| left
->data_type
== IR_DATA_FLOAT
) &&
232 right
->data_type
== IR_DATA_STRING
)) {
233 fprintf(stderr
, "[error] binary operation '%s' operand type mismatch\n", op_str
);
237 op
= calloc(sizeof(struct ir_op
), 1);
240 op
->op
= IR_OP_BINARY
;
241 op
->u
.binary
.type
= bin_op_type
;
242 op
->u
.binary
.left
= left
;
243 op
->u
.binary
.right
= right
;
245 /* we return a boolean, represented as signed numeric */
246 op
->data_type
= IR_DATA_NUMERIC
;
247 op
->signedness
= IR_SIGNED
;
258 struct ir_op
*make_op_binary_eq(struct ir_op
*left
, struct ir_op
*right
,
261 return make_op_binary_compare(AST_OP_EQ
, "==", left
, right
, side
);
265 struct ir_op
*make_op_binary_ne(struct ir_op
*left
, struct ir_op
*right
,
268 return make_op_binary_compare(AST_OP_NE
, "!=", left
, right
, side
);
272 struct ir_op
*make_op_binary_gt(struct ir_op
*left
, struct ir_op
*right
,
275 return make_op_binary_compare(AST_OP_GT
, ">", left
, right
, side
);
279 struct ir_op
*make_op_binary_lt(struct ir_op
*left
, struct ir_op
*right
,
282 return make_op_binary_compare(AST_OP_LT
, "<", left
, right
, side
);
286 struct ir_op
*make_op_binary_ge(struct ir_op
*left
, struct ir_op
*right
,
289 return make_op_binary_compare(AST_OP_GE
, ">=", left
, right
, side
);
293 struct ir_op
*make_op_binary_le(struct ir_op
*left
, struct ir_op
*right
,
296 return make_op_binary_compare(AST_OP_LE
, "<=", left
, right
, side
);
300 struct ir_op
*make_op_binary_logical(enum op_type bin_op_type
,
301 const char *op_str
, struct ir_op
*left
, struct ir_op
*right
,
304 struct ir_op
*op
= NULL
;
306 if (left
->data_type
== IR_DATA_UNKNOWN
307 || right
->data_type
== IR_DATA_UNKNOWN
) {
308 fprintf(stderr
, "[error] binary operation '%s' has unknown operand type\n", op_str
);
312 if (left
->data_type
== IR_DATA_STRING
313 || right
->data_type
== IR_DATA_STRING
) {
314 fprintf(stderr
, "[error] logical binary operation '%s' cannot have string operand\n", op_str
);
318 op
= calloc(sizeof(struct ir_op
), 1);
321 op
->op
= IR_OP_LOGICAL
;
322 op
->u
.binary
.type
= bin_op_type
;
323 op
->u
.binary
.left
= left
;
324 op
->u
.binary
.right
= right
;
326 /* we return a boolean, represented as signed numeric */
327 op
->data_type
= IR_DATA_NUMERIC
;
328 op
->signedness
= IR_SIGNED
;
339 struct ir_op
*make_op_binary_logical_and(struct ir_op
*left
, struct ir_op
*right
,
342 return make_op_binary_logical(AST_OP_AND
, "&&", left
, right
, side
);
346 struct ir_op
*make_op_binary_logical_or(struct ir_op
*left
, struct ir_op
*right
,
349 return make_op_binary_logical(AST_OP_OR
, "||", left
, right
, side
);
353 void filter_free_ir_recursive(struct ir_op
*op
)
360 fprintf(stderr
, "[error] Unknown op type in %s\n",
364 filter_free_ir_recursive(op
->u
.root
.child
);
367 switch (op
->data_type
) {
369 free(op
->u
.load
.u
.string
);
371 case IR_DATA_FIELD_REF
: /* fall-through */
372 case IR_DATA_GET_CONTEXT_REF
:
373 free(op
->u
.load
.u
.ref
);
380 filter_free_ir_recursive(op
->u
.unary
.child
);
383 filter_free_ir_recursive(op
->u
.binary
.left
);
384 filter_free_ir_recursive(op
->u
.binary
.right
);
387 filter_free_ir_recursive(op
->u
.logical
.left
);
388 filter_free_ir_recursive(op
->u
.logical
.right
);
395 struct ir_op
*make_expression(struct filter_parser_ctx
*ctx
,
396 struct filter_node
*node
, enum ir_side side
)
398 switch (node
->u
.expression
.type
) {
399 case AST_EXP_UNKNOWN
:
401 fprintf(stderr
, "[error] %s: unknown expression type\n", __func__
);
405 return make_op_load_string(node
->u
.expression
.u
.string
, side
);
406 case AST_EXP_CONSTANT
:
407 return make_op_load_numeric(node
->u
.expression
.u
.constant
,
409 case AST_EXP_FLOAT_CONSTANT
:
410 return make_op_load_float(node
->u
.expression
.u
.float_constant
,
412 case AST_EXP_IDENTIFIER
:
413 if (node
->u
.expression
.pre_op
!= AST_LINK_UNKNOWN
) {
414 fprintf(stderr
, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__
);
417 return make_op_load_field_ref(node
->u
.expression
.u
.identifier
,
419 case AST_EXP_GLOBAL_IDENTIFIER
:
421 struct filter_node
*next
;
423 if (node
->u
.expression
.pre_op
== AST_LINK_UNKNOWN
) {
424 fprintf(stderr
, "[error] %s: global identifiers need chained identifier \n", __func__
);
427 /* We currently only support $ctx (context) identifiers */
428 if (strncmp(node
->u
.expression
.u
.identifier
,
429 "$ctx", strlen("$ctx")) != 0) {
430 fprintf(stderr
, "[error] %s: \"%s\" global identifier is unknown. Only \"$ctx\" currently implemented.\n", __func__
, node
->u
.expression
.u
.identifier
);
433 next
= node
->u
.expression
.next
;
435 fprintf(stderr
, "[error] %s: Expecting a context name, e.g. \'$ctx.name\'.\n", __func__
);
438 if (next
->type
!= NODE_EXPRESSION
) {
439 fprintf(stderr
, "[error] %s: Expecting expression.\n", __func__
);
442 if (next
->u
.expression
.type
!= AST_EXP_IDENTIFIER
) {
443 fprintf(stderr
, "[error] %s: Expecting identifier.\n", __func__
);
446 if (next
->u
.expression
.pre_op
!= AST_LINK_UNKNOWN
) {
447 fprintf(stderr
, "[error] %s: dotted and dereferenced identifiers not supported after identifier\n", __func__
);
450 return make_op_load_get_context_ref(next
->u
.expression
.u
.identifier
,
454 return generate_ir_recursive(ctx
, node
->u
.expression
.u
.child
,
460 struct ir_op
*make_op(struct filter_parser_ctx
*ctx
,
461 struct filter_node
*node
, enum ir_side side
)
463 struct ir_op
*op
= NULL
, *lchild
, *rchild
;
464 const char *op_str
= "?";
466 switch (node
->u
.op
.type
) {
469 fprintf(stderr
, "[error] %s: unknown binary op type\n", __func__
);
473 * Binary operators other than comparators and logical and/or
474 * are not supported. If we ever want to support those, we will
475 * need a stack for the general case rather than just 2
476 * registers (see bytecode).
480 goto error_not_supported
;
483 goto error_not_supported
;
486 goto error_not_supported
;
489 goto error_not_supported
;
492 goto error_not_supported
;
495 goto error_not_supported
;
498 goto error_not_supported
;
501 goto error_not_supported
;
504 goto error_not_supported
;
507 goto error_not_supported
;
515 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
518 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_RIGHT
);
520 filter_free_ir_recursive(lchild
);
528 * Both children considered as left, since we need to
531 lchild
= generate_ir_recursive(ctx
, node
->u
.op
.lchild
, IR_LEFT
);
534 rchild
= generate_ir_recursive(ctx
, node
->u
.op
.rchild
, IR_LEFT
);
536 filter_free_ir_recursive(lchild
);
542 switch (node
->u
.op
.type
) {
544 op
= make_op_binary_logical_and(lchild
, rchild
, side
);
547 op
= make_op_binary_logical_or(lchild
, rchild
, side
);
550 op
= make_op_binary_eq(lchild
, rchild
, side
);
553 op
= make_op_binary_ne(lchild
, rchild
, side
);
556 op
= make_op_binary_gt(lchild
, rchild
, side
);
559 op
= make_op_binary_lt(lchild
, rchild
, side
);
562 op
= make_op_binary_ge(lchild
, rchild
, side
);
565 op
= make_op_binary_le(lchild
, rchild
, side
);
572 filter_free_ir_recursive(rchild
);
573 filter_free_ir_recursive(lchild
);
578 fprintf(stderr
, "[error] %s: binary operation '%s' not supported\n",
584 struct ir_op
*make_unary_op(struct filter_parser_ctx
*ctx
,
585 struct filter_node
*node
, enum ir_side side
)
587 const char *op_str
= "?";
589 switch (node
->u
.unary_op
.type
) {
590 case AST_UNARY_UNKNOWN
:
592 fprintf(stderr
, "[error] %s: unknown unary op type\n", __func__
);
597 struct ir_op
*op
, *child
;
599 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
603 op
= make_op_unary_plus(child
, side
);
605 filter_free_ir_recursive(child
);
610 case AST_UNARY_MINUS
:
612 struct ir_op
*op
, *child
;
614 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
618 op
= make_op_unary_minus(child
, side
);
620 filter_free_ir_recursive(child
);
627 struct ir_op
*op
, *child
;
629 child
= generate_ir_recursive(ctx
, node
->u
.unary_op
.child
,
633 op
= make_op_unary_not(child
, side
);
635 filter_free_ir_recursive(child
);
640 case AST_UNARY_BIN_NOT
:
643 goto error_not_supported
;
648 fprintf(stderr
, "[error] %s: unary operation '%s' not supported\n",
654 struct ir_op
*generate_ir_recursive(struct filter_parser_ctx
*ctx
,
655 struct filter_node
*node
, enum ir_side side
)
657 switch (node
->type
) {
660 fprintf(stderr
, "[error] %s: unknown node type\n", __func__
);
665 struct ir_op
*op
, *child
;
667 child
= generate_ir_recursive(ctx
, node
->u
.root
.child
,
671 op
= make_op_root(child
, side
);
673 filter_free_ir_recursive(child
);
678 case NODE_EXPRESSION
:
679 return make_expression(ctx
, node
, side
);
681 return make_op(ctx
, node
, side
);
683 return make_unary_op(ctx
, node
, side
);
689 void filter_ir_free(struct filter_parser_ctx
*ctx
)
691 filter_free_ir_recursive(ctx
->ir_root
);
696 int filter_visitor_ir_generate(struct filter_parser_ctx
*ctx
)
700 op
= generate_ir_recursive(ctx
, &ctx
->ast
->root
, IR_LEFT
);