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 insn
->op
= FILTER_OP_EQ_STRING
;
79 if (vstack_bx(stack
)->type
== REG_S64
)
80 insn
->op
= FILTER_OP_EQ_S64
;
82 insn
->op
= FILTER_OP_EQ_DOUBLE_S64
;
85 if (vstack_bx(stack
)->type
== REG_S64
)
86 insn
->op
= FILTER_OP_EQ_S64_DOUBLE
;
88 insn
->op
= FILTER_OP_EQ_DOUBLE
;
92 if (vstack_pop(stack
)) {
96 vstack_ax(stack
)->type
= REG_S64
;
97 next_pc
+= sizeof(struct binary_op
);
103 struct binary_op
*insn
= (struct binary_op
*) pc
;
105 switch(vstack_ax(stack
)->type
) {
107 ERR("unknown register type\n");
112 insn
->op
= FILTER_OP_NE_STRING
;
115 if (vstack_bx(stack
)->type
== REG_S64
)
116 insn
->op
= FILTER_OP_NE_S64
;
118 insn
->op
= FILTER_OP_NE_DOUBLE_S64
;
121 if (vstack_bx(stack
)->type
== REG_S64
)
122 insn
->op
= FILTER_OP_NE_S64_DOUBLE
;
124 insn
->op
= FILTER_OP_NE_DOUBLE
;
128 if (vstack_pop(stack
)) {
132 vstack_ax(stack
)->type
= REG_S64
;
133 next_pc
+= sizeof(struct binary_op
);
139 struct binary_op
*insn
= (struct binary_op
*) pc
;
141 switch(vstack_ax(stack
)->type
) {
143 ERR("unknown register type\n");
148 insn
->op
= FILTER_OP_GT_STRING
;
151 if (vstack_bx(stack
)->type
== REG_S64
)
152 insn
->op
= FILTER_OP_GT_S64
;
154 insn
->op
= FILTER_OP_GT_DOUBLE_S64
;
157 if (vstack_bx(stack
)->type
== REG_S64
)
158 insn
->op
= FILTER_OP_GT_S64_DOUBLE
;
160 insn
->op
= FILTER_OP_GT_DOUBLE
;
164 if (vstack_pop(stack
)) {
168 vstack_ax(stack
)->type
= REG_S64
;
169 next_pc
+= sizeof(struct binary_op
);
175 struct binary_op
*insn
= (struct binary_op
*) pc
;
177 switch(vstack_ax(stack
)->type
) {
179 ERR("unknown register type\n");
184 insn
->op
= FILTER_OP_LT_STRING
;
187 if (vstack_bx(stack
)->type
== REG_S64
)
188 insn
->op
= FILTER_OP_LT_S64
;
190 insn
->op
= FILTER_OP_LT_DOUBLE_S64
;
193 if (vstack_bx(stack
)->type
== REG_S64
)
194 insn
->op
= FILTER_OP_LT_S64_DOUBLE
;
196 insn
->op
= FILTER_OP_LT_DOUBLE
;
200 if (vstack_pop(stack
)) {
204 vstack_ax(stack
)->type
= REG_S64
;
205 next_pc
+= sizeof(struct binary_op
);
211 struct binary_op
*insn
= (struct binary_op
*) pc
;
213 switch(vstack_ax(stack
)->type
) {
215 ERR("unknown register type\n");
220 insn
->op
= FILTER_OP_GE_STRING
;
223 if (vstack_bx(stack
)->type
== REG_S64
)
224 insn
->op
= FILTER_OP_GE_S64
;
226 insn
->op
= FILTER_OP_GE_DOUBLE_S64
;
229 if (vstack_bx(stack
)->type
== REG_S64
)
230 insn
->op
= FILTER_OP_GE_S64_DOUBLE
;
232 insn
->op
= FILTER_OP_GE_DOUBLE
;
236 if (vstack_pop(stack
)) {
240 vstack_ax(stack
)->type
= REG_S64
;
241 next_pc
+= sizeof(struct binary_op
);
246 struct binary_op
*insn
= (struct binary_op
*) pc
;
248 switch(vstack_ax(stack
)->type
) {
250 ERR("unknown register type\n");
255 insn
->op
= FILTER_OP_LE_STRING
;
258 if (vstack_bx(stack
)->type
== REG_S64
)
259 insn
->op
= FILTER_OP_LE_S64
;
261 insn
->op
= FILTER_OP_LE_DOUBLE_S64
;
264 if (vstack_bx(stack
)->type
== REG_S64
)
265 insn
->op
= FILTER_OP_LE_S64_DOUBLE
;
267 insn
->op
= FILTER_OP_LE_DOUBLE
;
270 vstack_ax(stack
)->type
= REG_S64
;
271 next_pc
+= sizeof(struct binary_op
);
275 case FILTER_OP_EQ_STRING
:
276 case FILTER_OP_NE_STRING
:
277 case FILTER_OP_GT_STRING
:
278 case FILTER_OP_LT_STRING
:
279 case FILTER_OP_GE_STRING
:
280 case FILTER_OP_LE_STRING
:
281 case FILTER_OP_EQ_S64
:
282 case FILTER_OP_NE_S64
:
283 case FILTER_OP_GT_S64
:
284 case FILTER_OP_LT_S64
:
285 case FILTER_OP_GE_S64
:
286 case FILTER_OP_LE_S64
:
287 case FILTER_OP_EQ_DOUBLE
:
288 case FILTER_OP_NE_DOUBLE
:
289 case FILTER_OP_GT_DOUBLE
:
290 case FILTER_OP_LT_DOUBLE
:
291 case FILTER_OP_GE_DOUBLE
:
292 case FILTER_OP_LE_DOUBLE
:
293 case FILTER_OP_EQ_DOUBLE_S64
:
294 case FILTER_OP_NE_DOUBLE_S64
:
295 case FILTER_OP_GT_DOUBLE_S64
:
296 case FILTER_OP_LT_DOUBLE_S64
:
297 case FILTER_OP_GE_DOUBLE_S64
:
298 case FILTER_OP_LE_DOUBLE_S64
:
299 case FILTER_OP_EQ_S64_DOUBLE
:
300 case FILTER_OP_NE_S64_DOUBLE
:
301 case FILTER_OP_GT_S64_DOUBLE
:
302 case FILTER_OP_LT_S64_DOUBLE
:
303 case FILTER_OP_GE_S64_DOUBLE
:
304 case FILTER_OP_LE_S64_DOUBLE
:
307 if (vstack_pop(stack
)) {
311 vstack_ax(stack
)->type
= REG_S64
;
312 next_pc
+= sizeof(struct binary_op
);
317 case FILTER_OP_UNARY_PLUS
:
319 struct unary_op
*insn
= (struct unary_op
*) pc
;
321 switch(vstack_ax(stack
)->type
) {
323 ERR("unknown register type\n");
328 insn
->op
= FILTER_OP_UNARY_PLUS_S64
;
331 insn
->op
= FILTER_OP_UNARY_PLUS_DOUBLE
;
335 next_pc
+= sizeof(struct unary_op
);
339 case FILTER_OP_UNARY_MINUS
:
341 struct unary_op
*insn
= (struct unary_op
*) pc
;
343 switch(vstack_ax(stack
)->type
) {
345 ERR("unknown register type\n");
350 insn
->op
= FILTER_OP_UNARY_MINUS_S64
;
353 insn
->op
= FILTER_OP_UNARY_MINUS_DOUBLE
;
357 next_pc
+= sizeof(struct unary_op
);
361 case FILTER_OP_UNARY_NOT
:
363 struct unary_op
*insn
= (struct unary_op
*) pc
;
365 switch(vstack_ax(stack
)->type
) {
367 ERR("unknown register type\n");
372 insn
->op
= FILTER_OP_UNARY_NOT_S64
;
375 insn
->op
= FILTER_OP_UNARY_NOT_DOUBLE
;
379 next_pc
+= sizeof(struct unary_op
);
383 case FILTER_OP_UNARY_PLUS_S64
:
384 case FILTER_OP_UNARY_MINUS_S64
:
385 case FILTER_OP_UNARY_NOT_S64
:
386 case FILTER_OP_UNARY_PLUS_DOUBLE
:
387 case FILTER_OP_UNARY_MINUS_DOUBLE
:
388 case FILTER_OP_UNARY_NOT_DOUBLE
:
391 next_pc
+= sizeof(struct unary_op
);
399 /* Continue to next instruction */
400 /* Pop 1 when jump not taken */
401 if (vstack_pop(stack
)) {
405 next_pc
+= sizeof(struct logical_op
);
410 case FILTER_OP_LOAD_FIELD_REF
:
412 ERR("Unknown field ref type\n");
416 /* get context ref */
417 case FILTER_OP_GET_CONTEXT_REF
:
419 ERR("Unknown get context ref type\n");
423 case FILTER_OP_LOAD_FIELD_REF_STRING
:
424 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
425 case FILTER_OP_GET_CONTEXT_REF_STRING
:
427 if (vstack_push(stack
)) {
431 vstack_ax(stack
)->type
= REG_STRING
;
432 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
435 case FILTER_OP_LOAD_FIELD_REF_S64
:
436 case FILTER_OP_GET_CONTEXT_REF_S64
:
438 if (vstack_push(stack
)) {
442 vstack_ax(stack
)->type
= REG_S64
;
443 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
446 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
447 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
449 if (vstack_push(stack
)) {
453 vstack_ax(stack
)->type
= REG_DOUBLE
;
454 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
458 /* load from immediate operand */
459 case FILTER_OP_LOAD_STRING
:
461 struct load_op
*insn
= (struct load_op
*) pc
;
463 if (vstack_push(stack
)) {
467 vstack_ax(stack
)->type
= REG_STRING
;
468 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
472 case FILTER_OP_LOAD_S64
:
474 if (vstack_push(stack
)) {
478 vstack_ax(stack
)->type
= REG_S64
;
479 next_pc
+= sizeof(struct load_op
)
480 + sizeof(struct literal_numeric
);
484 case FILTER_OP_LOAD_DOUBLE
:
486 if (vstack_push(stack
)) {
490 vstack_ax(stack
)->type
= REG_DOUBLE
;
491 next_pc
+= sizeof(struct load_op
)
492 + sizeof(struct literal_double
);
497 case FILTER_OP_CAST_TO_S64
:
499 struct cast_op
*insn
= (struct cast_op
*) pc
;
501 switch (vstack_ax(stack
)->type
) {
503 ERR("unknown register type\n");
508 ERR("Cast op can only be applied to numeric or floating point registers\n");
512 insn
->op
= FILTER_OP_CAST_NOP
;
515 insn
->op
= FILTER_OP_CAST_DOUBLE_TO_S64
;
519 vstack_ax(stack
)->type
= REG_S64
;
520 next_pc
+= sizeof(struct cast_op
);
523 case FILTER_OP_CAST_DOUBLE_TO_S64
:
526 vstack_ax(stack
)->type
= REG_S64
;
527 next_pc
+= sizeof(struct cast_op
);
530 case FILTER_OP_CAST_NOP
:
532 next_pc
+= sizeof(struct cast_op
);