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
;
29 struct vreg reg
[NR_REG
];
32 for (i
= 0; i
< NR_REG
; i
++) {
33 reg
[i
].type
= REG_TYPE_UNKNOWN
;
37 start_pc
= &bytecode
->data
[0];
38 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
40 switch (*(filter_opcode_t
*) pc
) {
41 case FILTER_OP_UNKNOWN
:
43 ERR("unknown bytecode op %u\n",
44 (unsigned int) *(filter_opcode_t
*) pc
);
48 case FILTER_OP_RETURN
:
58 case FILTER_OP_RSHIFT
:
59 case FILTER_OP_LSHIFT
:
60 case FILTER_OP_BIN_AND
:
61 case FILTER_OP_BIN_OR
:
62 case FILTER_OP_BIN_XOR
:
63 ERR("unsupported bytecode op %u\n",
64 (unsigned int) *(filter_opcode_t
*) pc
);
70 struct binary_op
*insn
= (struct binary_op
*) pc
;
72 switch(reg
[REG_R0
].type
) {
74 ERR("unknown register type\n");
79 insn
->op
= FILTER_OP_EQ_STRING
;
82 if (reg
[REG_R1
].type
== REG_S64
)
83 insn
->op
= FILTER_OP_EQ_S64
;
85 insn
->op
= FILTER_OP_EQ_DOUBLE
;
88 insn
->op
= FILTER_OP_EQ_DOUBLE
;
91 reg
[REG_R0
].type
= REG_S64
;
92 next_pc
+= sizeof(struct binary_op
);
98 struct binary_op
*insn
= (struct binary_op
*) pc
;
100 switch(reg
[REG_R0
].type
) {
102 ERR("unknown register type\n");
107 insn
->op
= FILTER_OP_NE_STRING
;
110 if (reg
[REG_R1
].type
== REG_S64
)
111 insn
->op
= FILTER_OP_NE_S64
;
113 insn
->op
= FILTER_OP_NE_DOUBLE
;
116 insn
->op
= FILTER_OP_NE_DOUBLE
;
119 reg
[REG_R0
].type
= REG_S64
;
120 next_pc
+= sizeof(struct binary_op
);
126 struct binary_op
*insn
= (struct binary_op
*) pc
;
128 switch(reg
[REG_R0
].type
) {
130 ERR("unknown register type\n");
135 insn
->op
= FILTER_OP_GT_STRING
;
138 if (reg
[REG_R1
].type
== REG_S64
)
139 insn
->op
= FILTER_OP_GT_S64
;
141 insn
->op
= FILTER_OP_GT_DOUBLE
;
144 insn
->op
= FILTER_OP_GT_DOUBLE
;
147 reg
[REG_R0
].type
= REG_S64
;
148 next_pc
+= sizeof(struct binary_op
);
154 struct binary_op
*insn
= (struct binary_op
*) pc
;
156 switch(reg
[REG_R0
].type
) {
158 ERR("unknown register type\n");
163 insn
->op
= FILTER_OP_LT_STRING
;
166 if (reg
[REG_R1
].type
== REG_S64
)
167 insn
->op
= FILTER_OP_LT_S64
;
169 insn
->op
= FILTER_OP_LT_DOUBLE
;
172 insn
->op
= FILTER_OP_LT_DOUBLE
;
175 reg
[REG_R0
].type
= REG_S64
;
176 next_pc
+= sizeof(struct binary_op
);
182 struct binary_op
*insn
= (struct binary_op
*) pc
;
184 switch(reg
[REG_R0
].type
) {
186 ERR("unknown register type\n");
191 insn
->op
= FILTER_OP_GE_STRING
;
194 if (reg
[REG_R1
].type
== REG_S64
)
195 insn
->op
= FILTER_OP_GE_S64
;
197 insn
->op
= FILTER_OP_GE_DOUBLE
;
200 insn
->op
= FILTER_OP_GE_DOUBLE
;
203 reg
[REG_R0
].type
= REG_S64
;
204 next_pc
+= sizeof(struct binary_op
);
209 struct binary_op
*insn
= (struct binary_op
*) pc
;
211 switch(reg
[REG_R0
].type
) {
213 ERR("unknown register type\n");
218 insn
->op
= FILTER_OP_LE_STRING
;
221 if (reg
[REG_R1
].type
== REG_S64
)
222 insn
->op
= FILTER_OP_LE_S64
;
224 insn
->op
= FILTER_OP_LE_DOUBLE
;
227 insn
->op
= FILTER_OP_LE_DOUBLE
;
230 reg
[REG_R0
].type
= REG_S64
;
231 next_pc
+= sizeof(struct binary_op
);
235 case FILTER_OP_EQ_STRING
:
236 case FILTER_OP_NE_STRING
:
237 case FILTER_OP_GT_STRING
:
238 case FILTER_OP_LT_STRING
:
239 case FILTER_OP_GE_STRING
:
240 case FILTER_OP_LE_STRING
:
241 case FILTER_OP_EQ_S64
:
242 case FILTER_OP_NE_S64
:
243 case FILTER_OP_GT_S64
:
244 case FILTER_OP_LT_S64
:
245 case FILTER_OP_GE_S64
:
246 case FILTER_OP_LE_S64
:
247 case FILTER_OP_EQ_DOUBLE
:
248 case FILTER_OP_NE_DOUBLE
:
249 case FILTER_OP_GT_DOUBLE
:
250 case FILTER_OP_LT_DOUBLE
:
251 case FILTER_OP_GE_DOUBLE
:
252 case FILTER_OP_LE_DOUBLE
:
254 reg
[REG_R0
].type
= REG_S64
;
255 next_pc
+= sizeof(struct binary_op
);
260 case FILTER_OP_UNARY_PLUS
:
262 struct unary_op
*insn
= (struct unary_op
*) pc
;
264 switch(reg
[insn
->reg
].type
) {
266 ERR("unknown register type\n");
271 insn
->op
= FILTER_OP_UNARY_PLUS_S64
;
274 insn
->op
= FILTER_OP_UNARY_PLUS_DOUBLE
;
277 next_pc
+= sizeof(struct unary_op
);
281 case FILTER_OP_UNARY_MINUS
:
283 struct unary_op
*insn
= (struct unary_op
*) pc
;
285 switch(reg
[insn
->reg
].type
) {
287 ERR("unknown register type\n");
292 insn
->op
= FILTER_OP_UNARY_MINUS_S64
;
295 insn
->op
= FILTER_OP_UNARY_MINUS_DOUBLE
;
298 next_pc
+= sizeof(struct unary_op
);
302 case FILTER_OP_UNARY_NOT
:
304 struct unary_op
*insn
= (struct unary_op
*) pc
;
306 switch(reg
[insn
->reg
].type
) {
308 ERR("unknown register type\n");
313 insn
->op
= FILTER_OP_UNARY_NOT_S64
;
316 insn
->op
= FILTER_OP_UNARY_NOT_DOUBLE
;
319 next_pc
+= sizeof(struct unary_op
);
323 case FILTER_OP_UNARY_PLUS_S64
:
324 case FILTER_OP_UNARY_MINUS_S64
:
325 case FILTER_OP_UNARY_NOT_S64
:
326 case FILTER_OP_UNARY_PLUS_DOUBLE
:
327 case FILTER_OP_UNARY_MINUS_DOUBLE
:
328 case FILTER_OP_UNARY_NOT_DOUBLE
:
330 next_pc
+= sizeof(struct unary_op
);
338 next_pc
+= sizeof(struct logical_op
);
343 case FILTER_OP_LOAD_FIELD_REF
:
345 ERR("Unknown field ref type\n");
349 case FILTER_OP_LOAD_FIELD_REF_STRING
:
350 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
352 struct load_op
*insn
= (struct load_op
*) pc
;
354 reg
[insn
->reg
].type
= REG_STRING
;
355 reg
[insn
->reg
].literal
= 0;
356 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
359 case FILTER_OP_LOAD_FIELD_REF_S64
:
361 struct load_op
*insn
= (struct load_op
*) pc
;
363 reg
[insn
->reg
].type
= REG_S64
;
364 reg
[insn
->reg
].literal
= 0;
365 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
368 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
370 struct load_op
*insn
= (struct load_op
*) pc
;
372 reg
[insn
->reg
].type
= REG_DOUBLE
;
373 reg
[insn
->reg
].literal
= 0;
374 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
378 case FILTER_OP_LOAD_STRING
:
380 struct load_op
*insn
= (struct load_op
*) pc
;
382 reg
[insn
->reg
].type
= REG_STRING
;
383 reg
[insn
->reg
].literal
= 1;
384 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
388 case FILTER_OP_LOAD_S64
:
390 struct load_op
*insn
= (struct load_op
*) pc
;
392 reg
[insn
->reg
].type
= REG_S64
;
393 reg
[insn
->reg
].literal
= 1;
394 next_pc
+= sizeof(struct load_op
)
395 + sizeof(struct literal_numeric
);
399 case FILTER_OP_LOAD_DOUBLE
:
401 struct load_op
*insn
= (struct load_op
*) pc
;
403 reg
[insn
->reg
].type
= REG_DOUBLE
;
404 reg
[insn
->reg
].literal
= 1;
405 next_pc
+= sizeof(struct load_op
)
406 + sizeof(struct literal_double
);
411 case FILTER_OP_CAST_TO_S64
:
413 struct cast_op
*insn
= (struct cast_op
*) pc
;
415 switch (reg
[insn
->reg
].type
) {
417 ERR("unknown register type\n");
422 ERR("Cast op can only be applied to numeric or floating point registers\n");
426 insn
->op
= FILTER_OP_CAST_NOP
;
429 insn
->op
= FILTER_OP_CAST_DOUBLE_TO_S64
;
432 reg
[insn
->reg
].type
= REG_S64
;
433 next_pc
+= sizeof(struct cast_op
);
436 case FILTER_OP_CAST_DOUBLE_TO_S64
:
438 struct cast_op
*insn
= (struct cast_op
*) pc
;
440 reg
[insn
->reg
].type
= REG_S64
;
441 next_pc
+= sizeof(struct cast_op
);
444 case FILTER_OP_CAST_NOP
:
446 next_pc
+= sizeof(struct cast_op
);