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 if (vstack_bx(stack
)->type
== REG_STAR_GLOB_STRING
)
84 insn
->op
= FILTER_OP_EQ_STAR_GLOB_STRING
;
86 insn
->op
= FILTER_OP_EQ_STRING
;
88 case REG_STAR_GLOB_STRING
:
89 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
91 insn
->op
= FILTER_OP_EQ_STAR_GLOB_STRING
;
94 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
96 if (vstack_bx(stack
)->type
== REG_S64
)
97 insn
->op
= FILTER_OP_EQ_S64
;
99 insn
->op
= FILTER_OP_EQ_DOUBLE_S64
;
102 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
104 if (vstack_bx(stack
)->type
== REG_S64
)
105 insn
->op
= FILTER_OP_EQ_S64_DOUBLE
;
107 insn
->op
= FILTER_OP_EQ_DOUBLE
;
110 break; /* Dynamic typing. */
113 if (vstack_pop(stack
)) {
117 vstack_ax(stack
)->type
= REG_S64
;
118 next_pc
+= sizeof(struct binary_op
);
124 struct binary_op
*insn
= (struct binary_op
*) pc
;
126 switch(vstack_ax(stack
)->type
) {
128 ERR("unknown register type\n");
133 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
135 if (vstack_bx(stack
)->type
== REG_STAR_GLOB_STRING
)
136 insn
->op
= FILTER_OP_NE_STAR_GLOB_STRING
;
138 insn
->op
= FILTER_OP_NE_STRING
;
140 case REG_STAR_GLOB_STRING
:
141 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
143 insn
->op
= FILTER_OP_NE_STAR_GLOB_STRING
;
146 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
148 if (vstack_bx(stack
)->type
== REG_S64
)
149 insn
->op
= FILTER_OP_NE_S64
;
151 insn
->op
= FILTER_OP_NE_DOUBLE_S64
;
154 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
156 if (vstack_bx(stack
)->type
== REG_S64
)
157 insn
->op
= FILTER_OP_NE_S64_DOUBLE
;
159 insn
->op
= FILTER_OP_NE_DOUBLE
;
162 break; /* Dynamic typing. */
165 if (vstack_pop(stack
)) {
169 vstack_ax(stack
)->type
= REG_S64
;
170 next_pc
+= sizeof(struct binary_op
);
176 struct binary_op
*insn
= (struct binary_op
*) pc
;
178 switch(vstack_ax(stack
)->type
) {
180 ERR("unknown register type\n");
184 case REG_STAR_GLOB_STRING
:
185 ERR("invalid register type for > binary operator\n");
189 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
191 insn
->op
= FILTER_OP_GT_STRING
;
194 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
196 if (vstack_bx(stack
)->type
== REG_S64
)
197 insn
->op
= FILTER_OP_GT_S64
;
199 insn
->op
= FILTER_OP_GT_DOUBLE_S64
;
202 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
204 if (vstack_bx(stack
)->type
== REG_S64
)
205 insn
->op
= FILTER_OP_GT_S64_DOUBLE
;
207 insn
->op
= FILTER_OP_GT_DOUBLE
;
210 break; /* Dynamic typing. */
213 if (vstack_pop(stack
)) {
217 vstack_ax(stack
)->type
= REG_S64
;
218 next_pc
+= sizeof(struct binary_op
);
224 struct binary_op
*insn
= (struct binary_op
*) pc
;
226 switch(vstack_ax(stack
)->type
) {
228 ERR("unknown register type\n");
232 case REG_STAR_GLOB_STRING
:
233 ERR("invalid register type for < binary operator\n");
237 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
239 insn
->op
= FILTER_OP_LT_STRING
;
242 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
244 if (vstack_bx(stack
)->type
== REG_S64
)
245 insn
->op
= FILTER_OP_LT_S64
;
247 insn
->op
= FILTER_OP_LT_DOUBLE_S64
;
250 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
252 if (vstack_bx(stack
)->type
== REG_S64
)
253 insn
->op
= FILTER_OP_LT_S64_DOUBLE
;
255 insn
->op
= FILTER_OP_LT_DOUBLE
;
258 break; /* Dynamic typing. */
261 if (vstack_pop(stack
)) {
265 vstack_ax(stack
)->type
= REG_S64
;
266 next_pc
+= sizeof(struct binary_op
);
272 struct binary_op
*insn
= (struct binary_op
*) pc
;
274 switch(vstack_ax(stack
)->type
) {
276 ERR("unknown register type\n");
280 case REG_STAR_GLOB_STRING
:
281 ERR("invalid register type for >= binary operator\n");
285 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
287 insn
->op
= FILTER_OP_GE_STRING
;
290 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
292 if (vstack_bx(stack
)->type
== REG_S64
)
293 insn
->op
= FILTER_OP_GE_S64
;
295 insn
->op
= FILTER_OP_GE_DOUBLE_S64
;
298 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
300 if (vstack_bx(stack
)->type
== REG_S64
)
301 insn
->op
= FILTER_OP_GE_S64_DOUBLE
;
303 insn
->op
= FILTER_OP_GE_DOUBLE
;
306 break; /* Dynamic typing. */
309 if (vstack_pop(stack
)) {
313 vstack_ax(stack
)->type
= REG_S64
;
314 next_pc
+= sizeof(struct binary_op
);
319 struct binary_op
*insn
= (struct binary_op
*) pc
;
321 switch(vstack_ax(stack
)->type
) {
323 ERR("unknown register type\n");
327 case REG_STAR_GLOB_STRING
:
328 ERR("invalid register type for <= binary operator\n");
332 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
334 insn
->op
= FILTER_OP_LE_STRING
;
337 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
339 if (vstack_bx(stack
)->type
== REG_S64
)
340 insn
->op
= FILTER_OP_LE_S64
;
342 insn
->op
= FILTER_OP_LE_DOUBLE_S64
;
345 if (vstack_bx(stack
)->type
== REG_UNKNOWN
)
347 if (vstack_bx(stack
)->type
== REG_S64
)
348 insn
->op
= FILTER_OP_LE_S64_DOUBLE
;
350 insn
->op
= FILTER_OP_LE_DOUBLE
;
353 break; /* Dynamic typing. */
355 vstack_ax(stack
)->type
= REG_S64
;
356 next_pc
+= sizeof(struct binary_op
);
360 case FILTER_OP_EQ_STRING
:
361 case FILTER_OP_NE_STRING
:
362 case FILTER_OP_GT_STRING
:
363 case FILTER_OP_LT_STRING
:
364 case FILTER_OP_GE_STRING
:
365 case FILTER_OP_LE_STRING
:
366 case FILTER_OP_EQ_STAR_GLOB_STRING
:
367 case FILTER_OP_NE_STAR_GLOB_STRING
:
368 case FILTER_OP_EQ_S64
:
369 case FILTER_OP_NE_S64
:
370 case FILTER_OP_GT_S64
:
371 case FILTER_OP_LT_S64
:
372 case FILTER_OP_GE_S64
:
373 case FILTER_OP_LE_S64
:
374 case FILTER_OP_EQ_DOUBLE
:
375 case FILTER_OP_NE_DOUBLE
:
376 case FILTER_OP_GT_DOUBLE
:
377 case FILTER_OP_LT_DOUBLE
:
378 case FILTER_OP_GE_DOUBLE
:
379 case FILTER_OP_LE_DOUBLE
:
380 case FILTER_OP_EQ_DOUBLE_S64
:
381 case FILTER_OP_NE_DOUBLE_S64
:
382 case FILTER_OP_GT_DOUBLE_S64
:
383 case FILTER_OP_LT_DOUBLE_S64
:
384 case FILTER_OP_GE_DOUBLE_S64
:
385 case FILTER_OP_LE_DOUBLE_S64
:
386 case FILTER_OP_EQ_S64_DOUBLE
:
387 case FILTER_OP_NE_S64_DOUBLE
:
388 case FILTER_OP_GT_S64_DOUBLE
:
389 case FILTER_OP_LT_S64_DOUBLE
:
390 case FILTER_OP_GE_S64_DOUBLE
:
391 case FILTER_OP_LE_S64_DOUBLE
:
394 if (vstack_pop(stack
)) {
398 vstack_ax(stack
)->type
= REG_S64
;
399 next_pc
+= sizeof(struct binary_op
);
404 case FILTER_OP_UNARY_PLUS
:
406 struct unary_op
*insn
= (struct unary_op
*) pc
;
408 switch(vstack_ax(stack
)->type
) {
410 ERR("unknown register type\n");
415 insn
->op
= FILTER_OP_UNARY_PLUS_S64
;
418 insn
->op
= FILTER_OP_UNARY_PLUS_DOUBLE
;
420 case REG_UNKNOWN
: /* Dynamic typing. */
424 next_pc
+= sizeof(struct unary_op
);
428 case FILTER_OP_UNARY_MINUS
:
430 struct unary_op
*insn
= (struct unary_op
*) pc
;
432 switch(vstack_ax(stack
)->type
) {
434 ERR("unknown register type\n");
439 insn
->op
= FILTER_OP_UNARY_MINUS_S64
;
442 insn
->op
= FILTER_OP_UNARY_MINUS_DOUBLE
;
444 case REG_UNKNOWN
: /* Dynamic typing. */
448 next_pc
+= sizeof(struct unary_op
);
452 case FILTER_OP_UNARY_NOT
:
454 struct unary_op
*insn
= (struct unary_op
*) pc
;
456 switch(vstack_ax(stack
)->type
) {
458 ERR("unknown register type\n");
463 insn
->op
= FILTER_OP_UNARY_NOT_S64
;
466 insn
->op
= FILTER_OP_UNARY_NOT_DOUBLE
;
468 case REG_UNKNOWN
: /* Dynamic typing. */
472 next_pc
+= sizeof(struct unary_op
);
476 case FILTER_OP_UNARY_PLUS_S64
:
477 case FILTER_OP_UNARY_MINUS_S64
:
478 case FILTER_OP_UNARY_NOT_S64
:
479 case FILTER_OP_UNARY_PLUS_DOUBLE
:
480 case FILTER_OP_UNARY_MINUS_DOUBLE
:
481 case FILTER_OP_UNARY_NOT_DOUBLE
:
484 next_pc
+= sizeof(struct unary_op
);
492 /* Continue to next instruction */
493 /* Pop 1 when jump not taken */
494 if (vstack_pop(stack
)) {
498 next_pc
+= sizeof(struct logical_op
);
503 case FILTER_OP_LOAD_FIELD_REF
:
505 ERR("Unknown field ref type\n");
509 /* get context ref */
510 case FILTER_OP_GET_CONTEXT_REF
:
512 if (vstack_push(stack
)) {
516 vstack_ax(stack
)->type
= REG_UNKNOWN
;
517 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
520 case FILTER_OP_LOAD_FIELD_REF_STRING
:
521 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
522 case FILTER_OP_GET_CONTEXT_REF_STRING
:
524 if (vstack_push(stack
)) {
528 vstack_ax(stack
)->type
= REG_STRING
;
529 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
532 case FILTER_OP_LOAD_FIELD_REF_S64
:
533 case FILTER_OP_GET_CONTEXT_REF_S64
:
535 if (vstack_push(stack
)) {
539 vstack_ax(stack
)->type
= REG_S64
;
540 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
543 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
544 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
546 if (vstack_push(stack
)) {
550 vstack_ax(stack
)->type
= REG_DOUBLE
;
551 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
555 /* load from immediate operand */
556 case FILTER_OP_LOAD_STRING
:
558 struct load_op
*insn
= (struct load_op
*) pc
;
560 if (vstack_push(stack
)) {
564 vstack_ax(stack
)->type
= REG_STRING
;
565 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
569 case FILTER_OP_LOAD_STAR_GLOB_STRING
:
571 struct load_op
*insn
= (struct load_op
*) pc
;
573 if (vstack_push(stack
)) {
577 vstack_ax(stack
)->type
= REG_STAR_GLOB_STRING
;
578 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
582 case FILTER_OP_LOAD_S64
:
584 if (vstack_push(stack
)) {
588 vstack_ax(stack
)->type
= REG_S64
;
589 next_pc
+= sizeof(struct load_op
)
590 + sizeof(struct literal_numeric
);
594 case FILTER_OP_LOAD_DOUBLE
:
596 if (vstack_push(stack
)) {
600 vstack_ax(stack
)->type
= REG_DOUBLE
;
601 next_pc
+= sizeof(struct load_op
)
602 + sizeof(struct literal_double
);
607 case FILTER_OP_CAST_TO_S64
:
609 struct cast_op
*insn
= (struct cast_op
*) pc
;
611 switch (vstack_ax(stack
)->type
) {
613 ERR("unknown register type\n");
618 case REG_STAR_GLOB_STRING
:
619 ERR("Cast op can only be applied to numeric or floating point registers\n");
623 insn
->op
= FILTER_OP_CAST_NOP
;
626 insn
->op
= FILTER_OP_CAST_DOUBLE_TO_S64
;
632 vstack_ax(stack
)->type
= REG_S64
;
633 next_pc
+= sizeof(struct cast_op
);
636 case FILTER_OP_CAST_DOUBLE_TO_S64
:
639 vstack_ax(stack
)->type
= REG_S64
;
640 next_pc
+= sizeof(struct cast_op
);
643 case FILTER_OP_CAST_NOP
:
645 next_pc
+= sizeof(struct cast_op
);