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
24 #include "lttng-filter.h"
26 int lttng_filter_specialize_bytecode(struct bytecode_runtime
*bytecode
)
28 void *pc
, *next_pc
, *start_pc
;
31 struct vstack
*stack
= &_stack
;
35 start_pc
= &bytecode
->data
[0];
36 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
38 switch (*(filter_opcode_t
*) pc
) {
39 case FILTER_OP_UNKNOWN
:
41 ERR("unknown bytecode op %u\n",
42 (unsigned int) *(filter_opcode_t
*) pc
);
46 case FILTER_OP_RETURN
:
56 case FILTER_OP_RSHIFT
:
57 case FILTER_OP_LSHIFT
:
58 case FILTER_OP_BIN_AND
:
59 case FILTER_OP_BIN_OR
:
60 case FILTER_OP_BIN_XOR
:
61 ERR("unsupported bytecode op %u\n",
62 (unsigned int) *(filter_opcode_t
*) pc
);
68 struct binary_op
*insn
= (struct binary_op
*) pc
;
70 switch(vstack_ax(stack
)->type
) {
72 ERR("unknown register type\n");
77 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
79 insn
->op
= FILTER_OP_EQ_STRING
;
82 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
84 if (vstack_bx(stack
)->type
== REG_S64
)
85 insn
->op
= FILTER_OP_EQ_S64
;
87 insn
->op
= FILTER_OP_EQ_DOUBLE_S64
;
90 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
92 if (vstack_bx(stack
)->type
== REG_S64
)
93 insn
->op
= FILTER_OP_EQ_S64_DOUBLE
;
95 insn
->op
= FILTER_OP_EQ_DOUBLE
;
98 break; /* Dynamic typing. */
101 if (vstack_pop(stack
)) {
105 vstack_ax(stack
)->type
= REG_S64
;
106 next_pc
+= sizeof(struct binary_op
);
112 struct binary_op
*insn
= (struct binary_op
*) pc
;
114 switch(vstack_ax(stack
)->type
) {
116 ERR("unknown register type\n");
121 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
123 insn
->op
= FILTER_OP_NE_STRING
;
126 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
128 if (vstack_bx(stack
)->type
== REG_S64
)
129 insn
->op
= FILTER_OP_NE_S64
;
131 insn
->op
= FILTER_OP_NE_DOUBLE_S64
;
134 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
136 if (vstack_bx(stack
)->type
== REG_S64
)
137 insn
->op
= FILTER_OP_NE_S64_DOUBLE
;
139 insn
->op
= FILTER_OP_NE_DOUBLE
;
142 break; /* Dynamic typing. */
145 if (vstack_pop(stack
)) {
149 vstack_ax(stack
)->type
= REG_S64
;
150 next_pc
+= sizeof(struct binary_op
);
156 struct binary_op
*insn
= (struct binary_op
*) pc
;
158 switch(vstack_ax(stack
)->type
) {
160 ERR("unknown register type\n");
165 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
167 insn
->op
= FILTER_OP_GT_STRING
;
170 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
172 if (vstack_bx(stack
)->type
== REG_S64
)
173 insn
->op
= FILTER_OP_GT_S64
;
175 insn
->op
= FILTER_OP_GT_DOUBLE_S64
;
178 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
180 if (vstack_bx(stack
)->type
== REG_S64
)
181 insn
->op
= FILTER_OP_GT_S64_DOUBLE
;
183 insn
->op
= FILTER_OP_GT_DOUBLE
;
186 break; /* Dynamic typing. */
189 if (vstack_pop(stack
)) {
193 vstack_ax(stack
)->type
= REG_S64
;
194 next_pc
+= sizeof(struct binary_op
);
200 struct binary_op
*insn
= (struct binary_op
*) pc
;
202 switch(vstack_ax(stack
)->type
) {
204 ERR("unknown register type\n");
209 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
211 insn
->op
= FILTER_OP_LT_STRING
;
214 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
216 if (vstack_bx(stack
)->type
== REG_S64
)
217 insn
->op
= FILTER_OP_LT_S64
;
219 insn
->op
= FILTER_OP_LT_DOUBLE_S64
;
222 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
224 if (vstack_bx(stack
)->type
== REG_S64
)
225 insn
->op
= FILTER_OP_LT_S64_DOUBLE
;
227 insn
->op
= FILTER_OP_LT_DOUBLE
;
230 break; /* Dynamic typing. */
233 if (vstack_pop(stack
)) {
237 vstack_ax(stack
)->type
= REG_S64
;
238 next_pc
+= sizeof(struct binary_op
);
244 struct binary_op
*insn
= (struct binary_op
*) pc
;
246 switch(vstack_ax(stack
)->type
) {
248 ERR("unknown register type\n");
253 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
255 insn
->op
= FILTER_OP_GE_STRING
;
258 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
260 if (vstack_bx(stack
)->type
== REG_S64
)
261 insn
->op
= FILTER_OP_GE_S64
;
263 insn
->op
= FILTER_OP_GE_DOUBLE_S64
;
266 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
268 if (vstack_bx(stack
)->type
== REG_S64
)
269 insn
->op
= FILTER_OP_GE_S64_DOUBLE
;
271 insn
->op
= FILTER_OP_GE_DOUBLE
;
274 break; /* Dynamic typing. */
277 if (vstack_pop(stack
)) {
281 vstack_ax(stack
)->type
= REG_S64
;
282 next_pc
+= sizeof(struct binary_op
);
287 struct binary_op
*insn
= (struct binary_op
*) pc
;
289 switch(vstack_ax(stack
)->type
) {
291 ERR("unknown register type\n");
296 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
298 insn
->op
= FILTER_OP_LE_STRING
;
301 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
303 if (vstack_bx(stack
)->type
== REG_S64
)
304 insn
->op
= FILTER_OP_LE_S64
;
306 insn
->op
= FILTER_OP_LE_DOUBLE_S64
;
309 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
311 if (vstack_bx(stack
)->type
== REG_S64
)
312 insn
->op
= FILTER_OP_LE_S64_DOUBLE
;
314 insn
->op
= FILTER_OP_LE_DOUBLE
;
317 break; /* Dynamic typing. */
319 vstack_ax(stack
)->type
= REG_S64
;
320 next_pc
+= sizeof(struct binary_op
);
324 case FILTER_OP_EQ_STRING
:
325 case FILTER_OP_NE_STRING
:
326 case FILTER_OP_GT_STRING
:
327 case FILTER_OP_LT_STRING
:
328 case FILTER_OP_GE_STRING
:
329 case FILTER_OP_LE_STRING
:
330 case FILTER_OP_EQ_S64
:
331 case FILTER_OP_NE_S64
:
332 case FILTER_OP_GT_S64
:
333 case FILTER_OP_LT_S64
:
334 case FILTER_OP_GE_S64
:
335 case FILTER_OP_LE_S64
:
336 case FILTER_OP_EQ_DOUBLE
:
337 case FILTER_OP_NE_DOUBLE
:
338 case FILTER_OP_GT_DOUBLE
:
339 case FILTER_OP_LT_DOUBLE
:
340 case FILTER_OP_GE_DOUBLE
:
341 case FILTER_OP_LE_DOUBLE
:
342 case FILTER_OP_EQ_DOUBLE_S64
:
343 case FILTER_OP_NE_DOUBLE_S64
:
344 case FILTER_OP_GT_DOUBLE_S64
:
345 case FILTER_OP_LT_DOUBLE_S64
:
346 case FILTER_OP_GE_DOUBLE_S64
:
347 case FILTER_OP_LE_DOUBLE_S64
:
348 case FILTER_OP_EQ_S64_DOUBLE
:
349 case FILTER_OP_NE_S64_DOUBLE
:
350 case FILTER_OP_GT_S64_DOUBLE
:
351 case FILTER_OP_LT_S64_DOUBLE
:
352 case FILTER_OP_GE_S64_DOUBLE
:
353 case FILTER_OP_LE_S64_DOUBLE
:
356 if (vstack_pop(stack
)) {
360 vstack_ax(stack
)->type
= REG_S64
;
361 next_pc
+= sizeof(struct binary_op
);
366 case FILTER_OP_UNARY_PLUS
:
368 struct unary_op
*insn
= (struct unary_op
*) pc
;
370 switch(vstack_ax(stack
)->type
) {
372 ERR("unknown register type\n");
377 insn
->op
= FILTER_OP_UNARY_PLUS_S64
;
380 insn
->op
= FILTER_OP_UNARY_PLUS_DOUBLE
;
382 case REG_UNKNOWN
: /* Dynamic typing. */
386 next_pc
+= sizeof(struct unary_op
);
390 case FILTER_OP_UNARY_MINUS
:
392 struct unary_op
*insn
= (struct unary_op
*) pc
;
394 switch(vstack_ax(stack
)->type
) {
396 ERR("unknown register type\n");
401 insn
->op
= FILTER_OP_UNARY_MINUS_S64
;
404 insn
->op
= FILTER_OP_UNARY_MINUS_DOUBLE
;
406 case REG_UNKNOWN
: /* Dynamic typing. */
410 next_pc
+= sizeof(struct unary_op
);
414 case FILTER_OP_UNARY_NOT
:
416 struct unary_op
*insn
= (struct unary_op
*) pc
;
418 switch(vstack_ax(stack
)->type
) {
420 ERR("unknown register type\n");
425 insn
->op
= FILTER_OP_UNARY_NOT_S64
;
428 insn
->op
= FILTER_OP_UNARY_NOT_DOUBLE
;
430 case REG_UNKNOWN
: /* Dynamic typing. */
434 next_pc
+= sizeof(struct unary_op
);
438 case FILTER_OP_UNARY_PLUS_S64
:
439 case FILTER_OP_UNARY_MINUS_S64
:
440 case FILTER_OP_UNARY_NOT_S64
:
441 case FILTER_OP_UNARY_PLUS_DOUBLE
:
442 case FILTER_OP_UNARY_MINUS_DOUBLE
:
443 case FILTER_OP_UNARY_NOT_DOUBLE
:
446 next_pc
+= sizeof(struct unary_op
);
454 /* Continue to next instruction */
455 /* Pop 1 when jump not taken */
456 if (vstack_pop(stack
)) {
460 next_pc
+= sizeof(struct logical_op
);
465 case FILTER_OP_LOAD_FIELD_REF
:
467 ERR("Unknown field ref type\n");
471 /* get context ref */
472 case FILTER_OP_GET_CONTEXT_REF
:
474 if (vstack_push(stack
)) {
478 vstack_ax(stack
)->type
= REG_UNKNOWN
;
479 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
482 case FILTER_OP_LOAD_FIELD_REF_STRING
:
483 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
484 case FILTER_OP_GET_CONTEXT_REF_STRING
:
486 if (vstack_push(stack
)) {
490 vstack_ax(stack
)->type
= REG_STRING
;
491 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
494 case FILTER_OP_LOAD_FIELD_REF_S64
:
495 case FILTER_OP_GET_CONTEXT_REF_S64
:
497 if (vstack_push(stack
)) {
501 vstack_ax(stack
)->type
= REG_S64
;
502 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
505 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
506 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
508 if (vstack_push(stack
)) {
512 vstack_ax(stack
)->type
= REG_DOUBLE
;
513 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
517 /* load from immediate operand */
518 case FILTER_OP_LOAD_STRING
:
520 struct load_op
*insn
= (struct load_op
*) pc
;
522 if (vstack_push(stack
)) {
526 vstack_ax(stack
)->type
= REG_STRING
;
527 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
531 case FILTER_OP_LOAD_S64
:
533 if (vstack_push(stack
)) {
537 vstack_ax(stack
)->type
= REG_S64
;
538 next_pc
+= sizeof(struct load_op
)
539 + sizeof(struct literal_numeric
);
543 case FILTER_OP_LOAD_DOUBLE
:
545 if (vstack_push(stack
)) {
549 vstack_ax(stack
)->type
= REG_DOUBLE
;
550 next_pc
+= sizeof(struct load_op
)
551 + sizeof(struct literal_double
);
556 case FILTER_OP_CAST_TO_S64
:
558 struct cast_op
*insn
= (struct cast_op
*) pc
;
560 switch (vstack_ax(stack
)->type
) {
562 ERR("unknown register type\n");
567 ERR("Cast op can only be applied to numeric or floating point registers\n");
571 insn
->op
= FILTER_OP_CAST_NOP
;
574 insn
->op
= FILTER_OP_CAST_DOUBLE_TO_S64
;
580 vstack_ax(stack
)->type
= REG_S64
;
581 next_pc
+= sizeof(struct cast_op
);
584 case FILTER_OP_CAST_DOUBLE_TO_S64
:
587 vstack_ax(stack
)->type
= REG_S64
;
588 next_pc
+= sizeof(struct cast_op
);
591 case FILTER_OP_CAST_NOP
:
593 next_pc
+= sizeof(struct cast_op
);