2 * lttng-filter-specialize.c
4 * LTTng UST filter code specializer.
6 * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 #include "lttng-filter.h"
30 int lttng_filter_specialize_bytecode(struct bytecode_runtime
*bytecode
)
32 void *pc
, *next_pc
, *start_pc
;
35 struct vstack
*stack
= &_stack
;
39 start_pc
= &bytecode
->data
[0];
40 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
42 switch (*(filter_opcode_t
*) pc
) {
43 case FILTER_OP_UNKNOWN
:
45 ERR("unknown bytecode op %u\n",
46 (unsigned int) *(filter_opcode_t
*) pc
);
50 case FILTER_OP_RETURN
:
60 case FILTER_OP_RSHIFT
:
61 case FILTER_OP_LSHIFT
:
62 case FILTER_OP_BIN_AND
:
63 case FILTER_OP_BIN_OR
:
64 case FILTER_OP_BIN_XOR
:
65 ERR("unsupported bytecode op %u\n",
66 (unsigned int) *(filter_opcode_t
*) pc
);
72 struct binary_op
*insn
= (struct binary_op
*) pc
;
74 switch(vstack_ax(stack
)->type
) {
76 ERR("unknown register type\n");
81 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
83 insn
->op
= FILTER_OP_EQ_STRING
;
86 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
88 if (vstack_bx(stack
)->type
== REG_S64
)
89 insn
->op
= FILTER_OP_EQ_S64
;
91 insn
->op
= FILTER_OP_EQ_DOUBLE_S64
;
94 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
96 if (vstack_bx(stack
)->type
== REG_S64
)
97 insn
->op
= FILTER_OP_EQ_S64_DOUBLE
;
99 insn
->op
= FILTER_OP_EQ_DOUBLE
;
102 break; /* Dynamic typing. */
105 if (vstack_pop(stack
)) {
109 vstack_ax(stack
)->type
= REG_S64
;
110 next_pc
+= sizeof(struct binary_op
);
116 struct binary_op
*insn
= (struct binary_op
*) pc
;
118 switch(vstack_ax(stack
)->type
) {
120 ERR("unknown register type\n");
125 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
127 insn
->op
= FILTER_OP_NE_STRING
;
130 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
132 if (vstack_bx(stack
)->type
== REG_S64
)
133 insn
->op
= FILTER_OP_NE_S64
;
135 insn
->op
= FILTER_OP_NE_DOUBLE_S64
;
138 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
140 if (vstack_bx(stack
)->type
== REG_S64
)
141 insn
->op
= FILTER_OP_NE_S64_DOUBLE
;
143 insn
->op
= FILTER_OP_NE_DOUBLE
;
146 break; /* Dynamic typing. */
149 if (vstack_pop(stack
)) {
153 vstack_ax(stack
)->type
= REG_S64
;
154 next_pc
+= sizeof(struct binary_op
);
160 struct binary_op
*insn
= (struct binary_op
*) pc
;
162 switch(vstack_ax(stack
)->type
) {
164 ERR("unknown register type\n");
169 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
171 insn
->op
= FILTER_OP_GT_STRING
;
174 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
176 if (vstack_bx(stack
)->type
== REG_S64
)
177 insn
->op
= FILTER_OP_GT_S64
;
179 insn
->op
= FILTER_OP_GT_DOUBLE_S64
;
182 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
184 if (vstack_bx(stack
)->type
== REG_S64
)
185 insn
->op
= FILTER_OP_GT_S64_DOUBLE
;
187 insn
->op
= FILTER_OP_GT_DOUBLE
;
190 break; /* Dynamic typing. */
193 if (vstack_pop(stack
)) {
197 vstack_ax(stack
)->type
= REG_S64
;
198 next_pc
+= sizeof(struct binary_op
);
204 struct binary_op
*insn
= (struct binary_op
*) pc
;
206 switch(vstack_ax(stack
)->type
) {
208 ERR("unknown register type\n");
213 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
215 insn
->op
= FILTER_OP_LT_STRING
;
218 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
220 if (vstack_bx(stack
)->type
== REG_S64
)
221 insn
->op
= FILTER_OP_LT_S64
;
223 insn
->op
= FILTER_OP_LT_DOUBLE_S64
;
226 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
228 if (vstack_bx(stack
)->type
== REG_S64
)
229 insn
->op
= FILTER_OP_LT_S64_DOUBLE
;
231 insn
->op
= FILTER_OP_LT_DOUBLE
;
234 break; /* Dynamic typing. */
237 if (vstack_pop(stack
)) {
241 vstack_ax(stack
)->type
= REG_S64
;
242 next_pc
+= sizeof(struct binary_op
);
248 struct binary_op
*insn
= (struct binary_op
*) pc
;
250 switch(vstack_ax(stack
)->type
) {
252 ERR("unknown register type\n");
257 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
259 insn
->op
= FILTER_OP_GE_STRING
;
262 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
264 if (vstack_bx(stack
)->type
== REG_S64
)
265 insn
->op
= FILTER_OP_GE_S64
;
267 insn
->op
= FILTER_OP_GE_DOUBLE_S64
;
270 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
272 if (vstack_bx(stack
)->type
== REG_S64
)
273 insn
->op
= FILTER_OP_GE_S64_DOUBLE
;
275 insn
->op
= FILTER_OP_GE_DOUBLE
;
278 break; /* Dynamic typing. */
281 if (vstack_pop(stack
)) {
285 vstack_ax(stack
)->type
= REG_S64
;
286 next_pc
+= sizeof(struct binary_op
);
291 struct binary_op
*insn
= (struct binary_op
*) pc
;
293 switch(vstack_ax(stack
)->type
) {
295 ERR("unknown register type\n");
300 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
302 insn
->op
= FILTER_OP_LE_STRING
;
305 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
307 if (vstack_bx(stack
)->type
== REG_S64
)
308 insn
->op
= FILTER_OP_LE_S64
;
310 insn
->op
= FILTER_OP_LE_DOUBLE_S64
;
313 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
315 if (vstack_bx(stack
)->type
== REG_S64
)
316 insn
->op
= FILTER_OP_LE_S64_DOUBLE
;
318 insn
->op
= FILTER_OP_LE_DOUBLE
;
321 break; /* Dynamic typing. */
323 vstack_ax(stack
)->type
= REG_S64
;
324 next_pc
+= sizeof(struct binary_op
);
328 case FILTER_OP_EQ_STRING
:
329 case FILTER_OP_NE_STRING
:
330 case FILTER_OP_GT_STRING
:
331 case FILTER_OP_LT_STRING
:
332 case FILTER_OP_GE_STRING
:
333 case FILTER_OP_LE_STRING
:
334 case FILTER_OP_EQ_S64
:
335 case FILTER_OP_NE_S64
:
336 case FILTER_OP_GT_S64
:
337 case FILTER_OP_LT_S64
:
338 case FILTER_OP_GE_S64
:
339 case FILTER_OP_LE_S64
:
340 case FILTER_OP_EQ_DOUBLE
:
341 case FILTER_OP_NE_DOUBLE
:
342 case FILTER_OP_GT_DOUBLE
:
343 case FILTER_OP_LT_DOUBLE
:
344 case FILTER_OP_GE_DOUBLE
:
345 case FILTER_OP_LE_DOUBLE
:
346 case FILTER_OP_EQ_DOUBLE_S64
:
347 case FILTER_OP_NE_DOUBLE_S64
:
348 case FILTER_OP_GT_DOUBLE_S64
:
349 case FILTER_OP_LT_DOUBLE_S64
:
350 case FILTER_OP_GE_DOUBLE_S64
:
351 case FILTER_OP_LE_DOUBLE_S64
:
352 case FILTER_OP_EQ_S64_DOUBLE
:
353 case FILTER_OP_NE_S64_DOUBLE
:
354 case FILTER_OP_GT_S64_DOUBLE
:
355 case FILTER_OP_LT_S64_DOUBLE
:
356 case FILTER_OP_GE_S64_DOUBLE
:
357 case FILTER_OP_LE_S64_DOUBLE
:
360 if (vstack_pop(stack
)) {
364 vstack_ax(stack
)->type
= REG_S64
;
365 next_pc
+= sizeof(struct binary_op
);
370 case FILTER_OP_UNARY_PLUS
:
372 struct unary_op
*insn
= (struct unary_op
*) pc
;
374 switch(vstack_ax(stack
)->type
) {
376 ERR("unknown register type\n");
381 insn
->op
= FILTER_OP_UNARY_PLUS_S64
;
384 insn
->op
= FILTER_OP_UNARY_PLUS_DOUBLE
;
386 case REG_UNKNOWN
: /* Dynamic typing. */
390 next_pc
+= sizeof(struct unary_op
);
394 case FILTER_OP_UNARY_MINUS
:
396 struct unary_op
*insn
= (struct unary_op
*) pc
;
398 switch(vstack_ax(stack
)->type
) {
400 ERR("unknown register type\n");
405 insn
->op
= FILTER_OP_UNARY_MINUS_S64
;
408 insn
->op
= FILTER_OP_UNARY_MINUS_DOUBLE
;
410 case REG_UNKNOWN
: /* Dynamic typing. */
414 next_pc
+= sizeof(struct unary_op
);
418 case FILTER_OP_UNARY_NOT
:
420 struct unary_op
*insn
= (struct unary_op
*) pc
;
422 switch(vstack_ax(stack
)->type
) {
424 ERR("unknown register type\n");
429 insn
->op
= FILTER_OP_UNARY_NOT_S64
;
432 insn
->op
= FILTER_OP_UNARY_NOT_DOUBLE
;
434 case REG_UNKNOWN
: /* Dynamic typing. */
438 next_pc
+= sizeof(struct unary_op
);
442 case FILTER_OP_UNARY_PLUS_S64
:
443 case FILTER_OP_UNARY_MINUS_S64
:
444 case FILTER_OP_UNARY_NOT_S64
:
445 case FILTER_OP_UNARY_PLUS_DOUBLE
:
446 case FILTER_OP_UNARY_MINUS_DOUBLE
:
447 case FILTER_OP_UNARY_NOT_DOUBLE
:
450 next_pc
+= sizeof(struct unary_op
);
458 /* Continue to next instruction */
459 /* Pop 1 when jump not taken */
460 if (vstack_pop(stack
)) {
464 next_pc
+= sizeof(struct logical_op
);
469 case FILTER_OP_LOAD_FIELD_REF
:
471 ERR("Unknown field ref type\n");
475 /* get context ref */
476 case FILTER_OP_GET_CONTEXT_REF
:
478 if (vstack_push(stack
)) {
482 vstack_ax(stack
)->type
= REG_UNKNOWN
;
483 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
486 case FILTER_OP_LOAD_FIELD_REF_STRING
:
487 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
488 case FILTER_OP_GET_CONTEXT_REF_STRING
:
490 if (vstack_push(stack
)) {
494 vstack_ax(stack
)->type
= REG_STRING
;
495 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
498 case FILTER_OP_LOAD_FIELD_REF_S64
:
499 case FILTER_OP_GET_CONTEXT_REF_S64
:
501 if (vstack_push(stack
)) {
505 vstack_ax(stack
)->type
= REG_S64
;
506 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
509 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
510 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
512 if (vstack_push(stack
)) {
516 vstack_ax(stack
)->type
= REG_DOUBLE
;
517 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
521 /* load from immediate operand */
522 case FILTER_OP_LOAD_STRING
:
524 struct load_op
*insn
= (struct load_op
*) pc
;
526 if (vstack_push(stack
)) {
530 vstack_ax(stack
)->type
= REG_STRING
;
531 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
535 case FILTER_OP_LOAD_S64
:
537 if (vstack_push(stack
)) {
541 vstack_ax(stack
)->type
= REG_S64
;
542 next_pc
+= sizeof(struct load_op
)
543 + sizeof(struct literal_numeric
);
547 case FILTER_OP_LOAD_DOUBLE
:
549 if (vstack_push(stack
)) {
553 vstack_ax(stack
)->type
= REG_DOUBLE
;
554 next_pc
+= sizeof(struct load_op
)
555 + sizeof(struct literal_double
);
560 case FILTER_OP_CAST_TO_S64
:
562 struct cast_op
*insn
= (struct cast_op
*) pc
;
564 switch (vstack_ax(stack
)->type
) {
566 ERR("unknown register type\n");
571 ERR("Cast op can only be applied to numeric or floating point registers\n");
575 insn
->op
= FILTER_OP_CAST_NOP
;
578 insn
->op
= FILTER_OP_CAST_DOUBLE_TO_S64
;
584 vstack_ax(stack
)->type
= REG_S64
;
585 next_pc
+= sizeof(struct cast_op
);
588 case FILTER_OP_CAST_DOUBLE_TO_S64
:
591 vstack_ax(stack
)->type
= REG_S64
;
592 next_pc
+= sizeof(struct cast_op
);
595 case FILTER_OP_CAST_NOP
:
597 next_pc
+= sizeof(struct cast_op
);