Filter: double comparator produces s64
[lttng-ust.git] / liblttng-ust / lttng-filter-specialize.c
CommitLineData
97b58163
MD
1/*
2 * lttng-filter-specialize.c
3 *
4 * LTTng UST filter code specializer.
5 *
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
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.
12 *
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.
17 *
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
21 */
22
23#include "lttng-filter.h"
24
25int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
26{
27 void *pc, *next_pc, *start_pc;
28 int ret = -EINVAL;
29 struct vreg reg[NR_REG];
30 int i;
31
32 for (i = 0; i < NR_REG; i++) {
33 reg[i].type = REG_TYPE_UNKNOWN;
34 reg[i].literal = 0;
35 }
36
37 start_pc = &bytecode->data[0];
38 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
39 pc = next_pc) {
40 switch (*(filter_opcode_t *) pc) {
41 case FILTER_OP_UNKNOWN:
42 default:
43 ERR("unknown bytecode op %u\n",
44 (unsigned int) *(filter_opcode_t *) pc);
45 ret = -EINVAL;
46 goto end;
47
48 case FILTER_OP_RETURN:
49 ret = 0;
50 goto end;
51
52 /* binary */
53 case FILTER_OP_MUL:
54 case FILTER_OP_DIV:
55 case FILTER_OP_MOD:
56 case FILTER_OP_PLUS:
57 case FILTER_OP_MINUS:
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);
65 ret = -EINVAL;
66 goto end;
67
68 case FILTER_OP_EQ:
69 {
70 struct binary_op *insn = (struct binary_op *) pc;
71
72 switch(reg[REG_R0].type) {
73 default:
74 ERR("unknown register type\n");
75 ret = -EINVAL;
76 goto end;
77
78 case REG_STRING:
79 insn->op = FILTER_OP_EQ_STRING;
80 break;
81 case REG_S64:
82 if (reg[REG_R1].type == REG_S64)
83 insn->op = FILTER_OP_EQ_S64;
84 else
85 insn->op = FILTER_OP_EQ_DOUBLE;
86 break;
87 case REG_DOUBLE:
88 insn->op = FILTER_OP_EQ_DOUBLE;
89 break;
90 }
91 reg[REG_R0].type = REG_S64;
92 next_pc += sizeof(struct binary_op);
93 break;
94 }
95
96 case FILTER_OP_NE:
97 {
98 struct binary_op *insn = (struct binary_op *) pc;
99
100 switch(reg[REG_R0].type) {
101 default:
102 ERR("unknown register type\n");
103 ret = -EINVAL;
104 goto end;
105
106 case REG_STRING:
107 insn->op = FILTER_OP_NE_STRING;
108 break;
109 case REG_S64:
110 if (reg[REG_R1].type == REG_S64)
111 insn->op = FILTER_OP_NE_S64;
112 else
113 insn->op = FILTER_OP_NE_DOUBLE;
114 break;
115 case REG_DOUBLE:
116 insn->op = FILTER_OP_NE_DOUBLE;
117 break;
118 }
119 reg[REG_R0].type = REG_S64;
120 next_pc += sizeof(struct binary_op);
121 break;
122 }
123
124 case FILTER_OP_GT:
125 {
126 struct binary_op *insn = (struct binary_op *) pc;
127
128 switch(reg[REG_R0].type) {
129 default:
130 ERR("unknown register type\n");
131 ret = -EINVAL;
132 goto end;
133
134 case REG_STRING:
135 insn->op = FILTER_OP_GT_STRING;
136 break;
137 case REG_S64:
138 if (reg[REG_R1].type == REG_S64)
139 insn->op = FILTER_OP_GT_S64;
140 else
141 insn->op = FILTER_OP_GT_DOUBLE;
142 break;
143 case REG_DOUBLE:
144 insn->op = FILTER_OP_GT_DOUBLE;
145 break;
146 }
147 reg[REG_R0].type = REG_S64;
148 next_pc += sizeof(struct binary_op);
149 break;
150 }
151
152 case FILTER_OP_LT:
153 {
154 struct binary_op *insn = (struct binary_op *) pc;
155
156 switch(reg[REG_R0].type) {
157 default:
158 ERR("unknown register type\n");
159 ret = -EINVAL;
160 goto end;
161
162 case REG_STRING:
163 insn->op = FILTER_OP_LT_STRING;
164 break;
165 case REG_S64:
166 if (reg[REG_R1].type == REG_S64)
167 insn->op = FILTER_OP_LT_S64;
168 else
169 insn->op = FILTER_OP_LT_DOUBLE;
170 break;
171 case REG_DOUBLE:
172 insn->op = FILTER_OP_LT_DOUBLE;
173 break;
174 }
175 reg[REG_R0].type = REG_S64;
176 next_pc += sizeof(struct binary_op);
177 break;
178 }
179
180 case FILTER_OP_GE:
181 {
182 struct binary_op *insn = (struct binary_op *) pc;
183
184 switch(reg[REG_R0].type) {
185 default:
186 ERR("unknown register type\n");
187 ret = -EINVAL;
188 goto end;
189
190 case REG_STRING:
191 insn->op = FILTER_OP_GE_STRING;
192 break;
193 case REG_S64:
194 if (reg[REG_R1].type == REG_S64)
195 insn->op = FILTER_OP_GE_S64;
196 else
197 insn->op = FILTER_OP_GE_DOUBLE;
198 break;
199 case REG_DOUBLE:
200 insn->op = FILTER_OP_GE_DOUBLE;
201 break;
202 }
203 reg[REG_R0].type = REG_S64;
204 next_pc += sizeof(struct binary_op);
205 break;
206 }
207 case FILTER_OP_LE:
208 {
209 struct binary_op *insn = (struct binary_op *) pc;
210
211 switch(reg[REG_R0].type) {
212 default:
213 ERR("unknown register type\n");
214 ret = -EINVAL;
215 goto end;
216
217 case REG_STRING:
218 insn->op = FILTER_OP_LE_STRING;
219 break;
220 case REG_S64:
221 if (reg[REG_R1].type == REG_S64)
222 insn->op = FILTER_OP_LE_S64;
223 else
224 insn->op = FILTER_OP_LE_DOUBLE;
225 break;
226 case REG_DOUBLE:
227 insn->op = FILTER_OP_LE_DOUBLE;
228 break;
229 }
230 reg[REG_R0].type = REG_S64;
231 next_pc += sizeof(struct binary_op);
232 break;
233 }
234
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:
253 {
254 reg[REG_R0].type = REG_S64;
255 next_pc += sizeof(struct binary_op);
256 break;
257 }
258
259 /* unary */
260 case FILTER_OP_UNARY_PLUS:
261 {
262 struct unary_op *insn = (struct unary_op *) pc;
263
264 switch(reg[insn->reg].type) {
265 default:
266 ERR("unknown register type\n");
267 ret = -EINVAL;
268 goto end;
269
270 case REG_S64:
271 insn->op = FILTER_OP_UNARY_PLUS_S64;
272 break;
273 case REG_DOUBLE:
274 insn->op = FILTER_OP_UNARY_PLUS_DOUBLE;
275 break;
276 }
277 next_pc += sizeof(struct unary_op);
278 break;
279 }
280
281 case FILTER_OP_UNARY_MINUS:
282 {
283 struct unary_op *insn = (struct unary_op *) pc;
284
285 switch(reg[insn->reg].type) {
286 default:
287 ERR("unknown register type\n");
288 ret = -EINVAL;
289 goto end;
290
291 case REG_S64:
292 insn->op = FILTER_OP_UNARY_MINUS_S64;
293 break;
294 case REG_DOUBLE:
295 insn->op = FILTER_OP_UNARY_MINUS_DOUBLE;
296 break;
297 }
298 next_pc += sizeof(struct unary_op);
299 break;
300 }
301
302 case FILTER_OP_UNARY_NOT:
303 {
304 struct unary_op *insn = (struct unary_op *) pc;
305
306 switch(reg[insn->reg].type) {
307 default:
308 ERR("unknown register type\n");
309 ret = -EINVAL;
310 goto end;
311
312 case REG_S64:
313 insn->op = FILTER_OP_UNARY_NOT_S64;
314 break;
315 case REG_DOUBLE:
316 insn->op = FILTER_OP_UNARY_NOT_DOUBLE;
317 break;
318 }
319 next_pc += sizeof(struct unary_op);
320 break;
321 }
322
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:
329 {
330 next_pc += sizeof(struct unary_op);
331 break;
332 }
333
334 /* logical */
335 case FILTER_OP_AND:
336 case FILTER_OP_OR:
337 {
338 next_pc += sizeof(struct logical_op);
339 break;
340 }
341
342 /* load */
343 case FILTER_OP_LOAD_FIELD_REF:
344 {
345 ERR("Unknown field ref type\n");
346 ret = -EINVAL;
347 goto end;
348 }
349 case FILTER_OP_LOAD_FIELD_REF_STRING:
350 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
351 {
352 struct load_op *insn = (struct load_op *) pc;
353
354 reg[insn->reg].type = REG_STRING;
355 reg[insn->reg].literal = 0;
356 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
357 break;
358 }
359 case FILTER_OP_LOAD_FIELD_REF_S64:
360 {
361 struct load_op *insn = (struct load_op *) pc;
362
363 reg[insn->reg].type = REG_S64;
364 reg[insn->reg].literal = 0;
365 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
366 break;
367 }
368 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
369 {
370 struct load_op *insn = (struct load_op *) pc;
371
372 reg[insn->reg].type = REG_DOUBLE;
373 reg[insn->reg].literal = 0;
374 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
375 break;
376 }
377
378 case FILTER_OP_LOAD_STRING:
379 {
380 struct load_op *insn = (struct load_op *) pc;
381
382 reg[insn->reg].type = REG_STRING;
383 reg[insn->reg].literal = 1;
384 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
385 break;
386 }
387
388 case FILTER_OP_LOAD_S64:
389 {
390 struct load_op *insn = (struct load_op *) pc;
391
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);
396 break;
397 }
398
399 case FILTER_OP_LOAD_DOUBLE:
400 {
401 struct load_op *insn = (struct load_op *) pc;
402
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);
407 break;
408 }
409
410 /* cast */
411 case FILTER_OP_CAST_TO_S64:
412 {
413 struct cast_op *insn = (struct cast_op *) pc;
414
415 switch (reg[insn->reg].type) {
416 default:
417 ERR("unknown register type\n");
418 ret = -EINVAL;
419 goto end;
420
421 case REG_STRING:
422 ERR("Cast op can only be applied to numeric or floating point registers\n");
423 ret = -EINVAL;
424 goto end;
425 case REG_S64:
426 insn->op = FILTER_OP_CAST_NOP;
427 break;
428 case REG_DOUBLE:
429 insn->op = FILTER_OP_CAST_DOUBLE_TO_S64;
430 break;
431 }
432 reg[insn->reg].type = REG_S64;
433 next_pc += sizeof(struct cast_op);
434 break;
435 }
436 case FILTER_OP_CAST_DOUBLE_TO_S64:
437 {
438 struct cast_op *insn = (struct cast_op *) pc;
439
440 reg[insn->reg].type = REG_S64;
441 next_pc += sizeof(struct cast_op);
442 break;
443 }
444 case FILTER_OP_CAST_NOP:
445 {
446 next_pc += sizeof(struct cast_op);
447 break;
448 }
449
450
451 }
452 }
453end:
454 return ret;
455}
This page took 0.039771 seconds and 4 git commands to generate.