2 * lttng-filter-specialize.c
4 * LTTng UST filter code specializer.
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "lttng-filter.h"
25 int lttng_filter_specialize_bytecode(struct bytecode_runtime
*bytecode
)
27 void *pc
, *next_pc
, *start_pc
;
30 struct vstack
*stack
= &_stack
;
34 start_pc
= &bytecode
->data
[0];
35 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
37 switch (*(filter_opcode_t
*) pc
) {
38 case FILTER_OP_UNKNOWN
:
40 ERR("unknown bytecode op %u\n",
41 (unsigned int) *(filter_opcode_t
*) pc
);
45 case FILTER_OP_RETURN
:
55 case FILTER_OP_RSHIFT
:
56 case FILTER_OP_LSHIFT
:
57 case FILTER_OP_BIN_AND
:
58 case FILTER_OP_BIN_OR
:
59 case FILTER_OP_BIN_XOR
:
60 ERR("unsupported bytecode op %u\n",
61 (unsigned int) *(filter_opcode_t
*) pc
);
67 struct binary_op
*insn
= (struct binary_op
*) pc
;
69 switch(vstack_ax(stack
)->type
) {
71 ERR("unknown register type\n");
76 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
78 insn
->op
= FILTER_OP_EQ_STRING
;
81 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
83 if (vstack_bx(stack
)->type
== REG_S64
)
84 insn
->op
= FILTER_OP_EQ_S64
;
86 insn
->op
= FILTER_OP_EQ_DOUBLE_S64
;
89 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
91 if (vstack_bx(stack
)->type
== REG_S64
)
92 insn
->op
= FILTER_OP_EQ_S64_DOUBLE
;
94 insn
->op
= FILTER_OP_EQ_DOUBLE
;
97 break; /* Dynamic typing. */
100 if (vstack_pop(stack
)) {
104 vstack_ax(stack
)->type
= REG_S64
;
105 next_pc
+= sizeof(struct binary_op
);
111 struct binary_op
*insn
= (struct binary_op
*) pc
;
113 switch(vstack_ax(stack
)->type
) {
115 ERR("unknown register type\n");
120 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
122 insn
->op
= FILTER_OP_NE_STRING
;
125 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
127 if (vstack_bx(stack
)->type
== REG_S64
)
128 insn
->op
= FILTER_OP_NE_S64
;
130 insn
->op
= FILTER_OP_NE_DOUBLE_S64
;
133 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
135 if (vstack_bx(stack
)->type
== REG_S64
)
136 insn
->op
= FILTER_OP_NE_S64_DOUBLE
;
138 insn
->op
= FILTER_OP_NE_DOUBLE
;
141 break; /* Dynamic typing. */
144 if (vstack_pop(stack
)) {
148 vstack_ax(stack
)->type
= REG_S64
;
149 next_pc
+= sizeof(struct binary_op
);
155 struct binary_op
*insn
= (struct binary_op
*) pc
;
157 switch(vstack_ax(stack
)->type
) {
159 ERR("unknown register type\n");
164 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
166 insn
->op
= FILTER_OP_GT_STRING
;
169 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
171 if (vstack_bx(stack
)->type
== REG_S64
)
172 insn
->op
= FILTER_OP_GT_S64
;
174 insn
->op
= FILTER_OP_GT_DOUBLE_S64
;
177 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
179 if (vstack_bx(stack
)->type
== REG_S64
)
180 insn
->op
= FILTER_OP_GT_S64_DOUBLE
;
182 insn
->op
= FILTER_OP_GT_DOUBLE
;
185 break; /* Dynamic typing. */
188 if (vstack_pop(stack
)) {
192 vstack_ax(stack
)->type
= REG_S64
;
193 next_pc
+= sizeof(struct binary_op
);
199 struct binary_op
*insn
= (struct binary_op
*) pc
;
201 switch(vstack_ax(stack
)->type
) {
203 ERR("unknown register type\n");
208 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
210 insn
->op
= FILTER_OP_LT_STRING
;
213 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
215 if (vstack_bx(stack
)->type
== REG_S64
)
216 insn
->op
= FILTER_OP_LT_S64
;
218 insn
->op
= FILTER_OP_LT_DOUBLE_S64
;
221 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
223 if (vstack_bx(stack
)->type
== REG_S64
)
224 insn
->op
= FILTER_OP_LT_S64_DOUBLE
;
226 insn
->op
= FILTER_OP_LT_DOUBLE
;
229 break; /* Dynamic typing. */
232 if (vstack_pop(stack
)) {
236 vstack_ax(stack
)->type
= REG_S64
;
237 next_pc
+= sizeof(struct binary_op
);
243 struct binary_op
*insn
= (struct binary_op
*) pc
;
245 switch(vstack_ax(stack
)->type
) {
247 ERR("unknown register type\n");
252 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
254 insn
->op
= FILTER_OP_GE_STRING
;
257 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
259 if (vstack_bx(stack
)->type
== REG_S64
)
260 insn
->op
= FILTER_OP_GE_S64
;
262 insn
->op
= FILTER_OP_GE_DOUBLE_S64
;
265 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
267 if (vstack_bx(stack
)->type
== REG_S64
)
268 insn
->op
= FILTER_OP_GE_S64_DOUBLE
;
270 insn
->op
= FILTER_OP_GE_DOUBLE
;
273 break; /* Dynamic typing. */
276 if (vstack_pop(stack
)) {
280 vstack_ax(stack
)->type
= REG_S64
;
281 next_pc
+= sizeof(struct binary_op
);
286 struct binary_op
*insn
= (struct binary_op
*) pc
;
288 switch(vstack_ax(stack
)->type
) {
290 ERR("unknown register type\n");
295 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
297 insn
->op
= FILTER_OP_LE_STRING
;
300 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
302 if (vstack_bx(stack
)->type
== REG_S64
)
303 insn
->op
= FILTER_OP_LE_S64
;
305 insn
->op
= FILTER_OP_LE_DOUBLE_S64
;
308 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
310 if (vstack_bx(stack
)->type
== REG_S64
)
311 insn
->op
= FILTER_OP_LE_S64_DOUBLE
;
313 insn
->op
= FILTER_OP_LE_DOUBLE
;
316 break; /* Dynamic typing. */
318 vstack_ax(stack
)->type
= REG_S64
;
319 next_pc
+= sizeof(struct binary_op
);
323 case FILTER_OP_EQ_STRING
:
324 case FILTER_OP_NE_STRING
:
325 case FILTER_OP_GT_STRING
:
326 case FILTER_OP_LT_STRING
:
327 case FILTER_OP_GE_STRING
:
328 case FILTER_OP_LE_STRING
:
329 case FILTER_OP_EQ_S64
:
330 case FILTER_OP_NE_S64
:
331 case FILTER_OP_GT_S64
:
332 case FILTER_OP_LT_S64
:
333 case FILTER_OP_GE_S64
:
334 case FILTER_OP_LE_S64
:
335 case FILTER_OP_EQ_DOUBLE
:
336 case FILTER_OP_NE_DOUBLE
:
337 case FILTER_OP_GT_DOUBLE
:
338 case FILTER_OP_LT_DOUBLE
:
339 case FILTER_OP_GE_DOUBLE
:
340 case FILTER_OP_LE_DOUBLE
:
341 case FILTER_OP_EQ_DOUBLE_S64
:
342 case FILTER_OP_NE_DOUBLE_S64
:
343 case FILTER_OP_GT_DOUBLE_S64
:
344 case FILTER_OP_LT_DOUBLE_S64
:
345 case FILTER_OP_GE_DOUBLE_S64
:
346 case FILTER_OP_LE_DOUBLE_S64
:
347 case FILTER_OP_EQ_S64_DOUBLE
:
348 case FILTER_OP_NE_S64_DOUBLE
:
349 case FILTER_OP_GT_S64_DOUBLE
:
350 case FILTER_OP_LT_S64_DOUBLE
:
351 case FILTER_OP_GE_S64_DOUBLE
:
352 case FILTER_OP_LE_S64_DOUBLE
:
355 if (vstack_pop(stack
)) {
359 vstack_ax(stack
)->type
= REG_S64
;
360 next_pc
+= sizeof(struct binary_op
);
365 case FILTER_OP_UNARY_PLUS
:
367 struct unary_op
*insn
= (struct unary_op
*) pc
;
369 switch(vstack_ax(stack
)->type
) {
371 ERR("unknown register type\n");
376 insn
->op
= FILTER_OP_UNARY_PLUS_S64
;
379 insn
->op
= FILTER_OP_UNARY_PLUS_DOUBLE
;
381 case REG_UNKNOWN
: /* Dynamic typing. */
385 next_pc
+= sizeof(struct unary_op
);
389 case FILTER_OP_UNARY_MINUS
:
391 struct unary_op
*insn
= (struct unary_op
*) pc
;
393 switch(vstack_ax(stack
)->type
) {
395 ERR("unknown register type\n");
400 insn
->op
= FILTER_OP_UNARY_MINUS_S64
;
403 insn
->op
= FILTER_OP_UNARY_MINUS_DOUBLE
;
405 case REG_UNKNOWN
: /* Dynamic typing. */
409 next_pc
+= sizeof(struct unary_op
);
413 case FILTER_OP_UNARY_NOT
:
415 struct unary_op
*insn
= (struct unary_op
*) pc
;
417 switch(vstack_ax(stack
)->type
) {
419 ERR("unknown register type\n");
424 insn
->op
= FILTER_OP_UNARY_NOT_S64
;
427 insn
->op
= FILTER_OP_UNARY_NOT_DOUBLE
;
429 case REG_UNKNOWN
: /* Dynamic typing. */
433 next_pc
+= sizeof(struct unary_op
);
437 case FILTER_OP_UNARY_PLUS_S64
:
438 case FILTER_OP_UNARY_MINUS_S64
:
439 case FILTER_OP_UNARY_NOT_S64
:
440 case FILTER_OP_UNARY_PLUS_DOUBLE
:
441 case FILTER_OP_UNARY_MINUS_DOUBLE
:
442 case FILTER_OP_UNARY_NOT_DOUBLE
:
445 next_pc
+= sizeof(struct unary_op
);
453 /* Continue to next instruction */
454 /* Pop 1 when jump not taken */
455 if (vstack_pop(stack
)) {
459 next_pc
+= sizeof(struct logical_op
);
464 case FILTER_OP_LOAD_FIELD_REF
:
466 ERR("Unknown field ref type\n");
470 /* get context ref */
471 case FILTER_OP_GET_CONTEXT_REF
:
473 if (vstack_push(stack
)) {
477 vstack_ax(stack
)->type
= REG_UNKNOWN
;
478 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
481 case FILTER_OP_LOAD_FIELD_REF_STRING
:
482 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
483 case FILTER_OP_GET_CONTEXT_REF_STRING
:
485 if (vstack_push(stack
)) {
489 vstack_ax(stack
)->type
= REG_STRING
;
490 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
493 case FILTER_OP_LOAD_FIELD_REF_S64
:
494 case FILTER_OP_GET_CONTEXT_REF_S64
:
496 if (vstack_push(stack
)) {
500 vstack_ax(stack
)->type
= REG_S64
;
501 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
504 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
505 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
507 if (vstack_push(stack
)) {
511 vstack_ax(stack
)->type
= REG_DOUBLE
;
512 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
516 /* load from immediate operand */
517 case FILTER_OP_LOAD_STRING
:
519 struct load_op
*insn
= (struct load_op
*) pc
;
521 if (vstack_push(stack
)) {
525 vstack_ax(stack
)->type
= REG_STRING
;
526 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
530 case FILTER_OP_LOAD_S64
:
532 if (vstack_push(stack
)) {
536 vstack_ax(stack
)->type
= REG_S64
;
537 next_pc
+= sizeof(struct load_op
)
538 + sizeof(struct literal_numeric
);
542 case FILTER_OP_LOAD_DOUBLE
:
544 if (vstack_push(stack
)) {
548 vstack_ax(stack
)->type
= REG_DOUBLE
;
549 next_pc
+= sizeof(struct load_op
)
550 + sizeof(struct literal_double
);
555 case FILTER_OP_CAST_TO_S64
:
557 struct cast_op
*insn
= (struct cast_op
*) pc
;
559 switch (vstack_ax(stack
)->type
) {
561 ERR("unknown register type\n");
566 ERR("Cast op can only be applied to numeric or floating point registers\n");
570 insn
->op
= FILTER_OP_CAST_NOP
;
573 insn
->op
= FILTER_OP_CAST_DOUBLE_TO_S64
;
579 vstack_ax(stack
)->type
= REG_S64
;
580 next_pc
+= sizeof(struct cast_op
);
583 case FILTER_OP_CAST_DOUBLE_TO_S64
:
586 vstack_ax(stack
)->type
= REG_S64
;
587 next_pc
+= sizeof(struct cast_op
);
590 case FILTER_OP_CAST_NOP
:
592 next_pc
+= sizeof(struct cast_op
);