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
;
85 insn
->op
= FILTER_OP_EQ_DOUBLE
;
89 if (vstack_pop(stack
)) {
93 vstack_ax(stack
)->type
= REG_S64
;
94 next_pc
+= sizeof(struct binary_op
);
100 struct binary_op
*insn
= (struct binary_op
*) pc
;
102 switch(vstack_ax(stack
)->type
) {
104 ERR("unknown register type\n");
109 insn
->op
= FILTER_OP_NE_STRING
;
112 if (vstack_bx(stack
)->type
== REG_S64
)
113 insn
->op
= FILTER_OP_NE_S64
;
115 insn
->op
= FILTER_OP_NE_DOUBLE
;
118 insn
->op
= FILTER_OP_NE_DOUBLE
;
122 if (vstack_pop(stack
)) {
126 vstack_ax(stack
)->type
= REG_S64
;
127 next_pc
+= sizeof(struct binary_op
);
133 struct binary_op
*insn
= (struct binary_op
*) pc
;
135 switch(vstack_ax(stack
)->type
) {
137 ERR("unknown register type\n");
142 insn
->op
= FILTER_OP_GT_STRING
;
145 if (vstack_bx(stack
)->type
== REG_S64
)
146 insn
->op
= FILTER_OP_GT_S64
;
148 insn
->op
= FILTER_OP_GT_DOUBLE
;
151 insn
->op
= FILTER_OP_GT_DOUBLE
;
155 if (vstack_pop(stack
)) {
159 vstack_ax(stack
)->type
= REG_S64
;
160 next_pc
+= sizeof(struct binary_op
);
166 struct binary_op
*insn
= (struct binary_op
*) pc
;
168 switch(vstack_ax(stack
)->type
) {
170 ERR("unknown register type\n");
175 insn
->op
= FILTER_OP_LT_STRING
;
178 if (vstack_bx(stack
)->type
== REG_S64
)
179 insn
->op
= FILTER_OP_LT_S64
;
181 insn
->op
= FILTER_OP_LT_DOUBLE
;
184 insn
->op
= FILTER_OP_LT_DOUBLE
;
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 insn
->op
= FILTER_OP_GE_STRING
;
211 if (vstack_bx(stack
)->type
== REG_S64
)
212 insn
->op
= FILTER_OP_GE_S64
;
214 insn
->op
= FILTER_OP_GE_DOUBLE
;
217 insn
->op
= FILTER_OP_GE_DOUBLE
;
221 if (vstack_pop(stack
)) {
225 vstack_ax(stack
)->type
= REG_S64
;
226 next_pc
+= sizeof(struct binary_op
);
231 struct binary_op
*insn
= (struct binary_op
*) pc
;
233 switch(vstack_ax(stack
)->type
) {
235 ERR("unknown register type\n");
240 insn
->op
= FILTER_OP_LE_STRING
;
243 if (vstack_bx(stack
)->type
== REG_S64
)
244 insn
->op
= FILTER_OP_LE_S64
;
246 insn
->op
= FILTER_OP_LE_DOUBLE
;
249 insn
->op
= FILTER_OP_LE_DOUBLE
;
252 vstack_ax(stack
)->type
= REG_S64
;
253 next_pc
+= sizeof(struct binary_op
);
257 case FILTER_OP_EQ_STRING
:
258 case FILTER_OP_NE_STRING
:
259 case FILTER_OP_GT_STRING
:
260 case FILTER_OP_LT_STRING
:
261 case FILTER_OP_GE_STRING
:
262 case FILTER_OP_LE_STRING
:
263 case FILTER_OP_EQ_S64
:
264 case FILTER_OP_NE_S64
:
265 case FILTER_OP_GT_S64
:
266 case FILTER_OP_LT_S64
:
267 case FILTER_OP_GE_S64
:
268 case FILTER_OP_LE_S64
:
269 case FILTER_OP_EQ_DOUBLE
:
270 case FILTER_OP_NE_DOUBLE
:
271 case FILTER_OP_GT_DOUBLE
:
272 case FILTER_OP_LT_DOUBLE
:
273 case FILTER_OP_GE_DOUBLE
:
274 case FILTER_OP_LE_DOUBLE
:
277 if (vstack_pop(stack
)) {
281 vstack_ax(stack
)->type
= REG_S64
;
282 next_pc
+= sizeof(struct binary_op
);
287 case FILTER_OP_UNARY_PLUS
:
289 struct unary_op
*insn
= (struct unary_op
*) pc
;
291 switch(vstack_ax(stack
)->type
) {
293 ERR("unknown register type\n");
298 insn
->op
= FILTER_OP_UNARY_PLUS_S64
;
301 insn
->op
= FILTER_OP_UNARY_PLUS_DOUBLE
;
305 next_pc
+= sizeof(struct unary_op
);
309 case FILTER_OP_UNARY_MINUS
:
311 struct unary_op
*insn
= (struct unary_op
*) pc
;
313 switch(vstack_ax(stack
)->type
) {
315 ERR("unknown register type\n");
320 insn
->op
= FILTER_OP_UNARY_MINUS_S64
;
323 insn
->op
= FILTER_OP_UNARY_MINUS_DOUBLE
;
327 next_pc
+= sizeof(struct unary_op
);
331 case FILTER_OP_UNARY_NOT
:
333 struct unary_op
*insn
= (struct unary_op
*) pc
;
335 switch(vstack_ax(stack
)->type
) {
337 ERR("unknown register type\n");
342 insn
->op
= FILTER_OP_UNARY_NOT_S64
;
345 insn
->op
= FILTER_OP_UNARY_NOT_DOUBLE
;
349 next_pc
+= sizeof(struct unary_op
);
353 case FILTER_OP_UNARY_PLUS_S64
:
354 case FILTER_OP_UNARY_MINUS_S64
:
355 case FILTER_OP_UNARY_NOT_S64
:
356 case FILTER_OP_UNARY_PLUS_DOUBLE
:
357 case FILTER_OP_UNARY_MINUS_DOUBLE
:
358 case FILTER_OP_UNARY_NOT_DOUBLE
:
361 next_pc
+= sizeof(struct unary_op
);
369 next_pc
+= sizeof(struct logical_op
);
374 case FILTER_OP_LOAD_FIELD_REF
:
376 ERR("Unknown field ref type\n");
380 case FILTER_OP_LOAD_FIELD_REF_STRING
:
381 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
383 if (vstack_push(stack
)) {
387 vstack_ax(stack
)->type
= REG_STRING
;
388 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
391 case FILTER_OP_LOAD_FIELD_REF_S64
:
393 if (vstack_push(stack
)) {
397 vstack_ax(stack
)->type
= REG_S64
;
398 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
401 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
403 if (vstack_push(stack
)) {
407 vstack_ax(stack
)->type
= REG_DOUBLE
;
408 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
412 case FILTER_OP_LOAD_STRING
:
414 struct load_op
*insn
= (struct load_op
*) pc
;
416 if (vstack_push(stack
)) {
420 vstack_ax(stack
)->type
= REG_STRING
;
421 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
425 case FILTER_OP_LOAD_S64
:
427 if (vstack_push(stack
)) {
431 vstack_ax(stack
)->type
= REG_S64
;
432 next_pc
+= sizeof(struct load_op
)
433 + sizeof(struct literal_numeric
);
437 case FILTER_OP_LOAD_DOUBLE
:
439 if (vstack_push(stack
)) {
443 vstack_ax(stack
)->type
= REG_DOUBLE
;
444 next_pc
+= sizeof(struct load_op
)
445 + sizeof(struct literal_double
);
450 case FILTER_OP_CAST_TO_S64
:
452 struct cast_op
*insn
= (struct cast_op
*) pc
;
454 switch (vstack_ax(stack
)->type
) {
456 ERR("unknown register type\n");
461 ERR("Cast op can only be applied to numeric or floating point registers\n");
465 insn
->op
= FILTER_OP_CAST_NOP
;
468 insn
->op
= FILTER_OP_CAST_DOUBLE_TO_S64
;
472 vstack_ax(stack
)->type
= REG_S64
;
473 next_pc
+= sizeof(struct cast_op
);
476 case FILTER_OP_CAST_DOUBLE_TO_S64
:
479 vstack_ax(stack
)->type
= REG_S64
;
480 next_pc
+= sizeof(struct cast_op
);
483 case FILTER_OP_CAST_NOP
:
485 next_pc
+= sizeof(struct cast_op
);