Filter: specialize double-s64 binary comparators
[lttng-ust.git] / liblttng-ust / lttng-filter-interpreter.c
1 /*
2 * lttng-filter-interpreter.c
3 *
4 * LTTng UST filter interpreter.
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
25 /*
26 * -1: wildcard found.
27 * -2: unknown escape char.
28 * 0: normal char.
29 */
30
31 static
32 int parse_char(const char **p)
33 {
34 switch (**p) {
35 case '\\':
36 (*p)++;
37 switch (**p) {
38 case '\\':
39 case '*':
40 return 0;
41 default:
42 return -2;
43 }
44 case '*':
45 return -1;
46 default:
47 return 0;
48 }
49 }
50
51 static
52 int stack_strcmp(struct estack *stack, const char *cmp_type)
53 {
54 const char *p = estack_bx(stack)->u.s.str, *q = estack_ax(stack)->u.s.str;
55 int ret;
56 int diff;
57
58 for (;;) {
59 int escaped_r0 = 0;
60
61 if (unlikely(p - estack_bx(stack)->u.s.str > estack_bx(stack)->u.s.seq_len || *p == '\0')) {
62 if (q - estack_ax(stack)->u.s.str > estack_ax(stack)->u.s.seq_len || *q == '\0')
63 diff = 0;
64 else
65 diff = -1;
66 break;
67 }
68 if (unlikely(q - estack_ax(stack)->u.s.str > estack_ax(stack)->u.s.seq_len || *q == '\0')) {
69 if (p - estack_bx(stack)->u.s.str > estack_bx(stack)->u.s.seq_len || *p == '\0')
70 diff = 0;
71 else
72 diff = 1;
73 break;
74 }
75 if (estack_bx(stack)->u.s.literal) {
76 ret = parse_char(&p);
77 if (ret == -1) {
78 return 0;
79 } else if (ret == -2) {
80 escaped_r0 = 1;
81 }
82 /* else compare both char */
83 }
84 if (estack_ax(stack)->u.s.literal) {
85 ret = parse_char(&q);
86 if (ret == -1) {
87 return 0;
88 } else if (ret == -2) {
89 if (!escaped_r0)
90 return -1;
91 } else {
92 if (escaped_r0)
93 return 1;
94 }
95 } else {
96 if (escaped_r0)
97 return 1;
98 }
99 diff = *p - *q;
100 if (diff != 0)
101 break;
102 p++;
103 q++;
104 }
105 return diff;
106 }
107
108 int lttng_filter_false(void *filter_data,
109 const char *filter_stack_data)
110 {
111 return 0;
112 }
113
114 #ifdef INTERPRETER_USE_SWITCH
115
116 /*
117 * Fallback for compilers that do not support taking address of labels.
118 */
119
120 #define START_OP \
121 start_pc = &bytecode->data[0]; \
122 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
123 pc = next_pc) { \
124 dbg_printf("Executing op %s (%u)\n", \
125 print_op((unsigned int) *(filter_opcode_t *) pc), \
126 (unsigned int) *(filter_opcode_t *) pc); \
127 switch (*(filter_opcode_t *) pc) {
128
129 #define OP(name) case name
130
131 #define PO break
132
133 #define END_OP } \
134 }
135
136 #else
137
138 /*
139 * Dispatch-table based interpreter.
140 */
141
142 #define START_OP \
143 start_pc = &bytecode->data[0]; \
144 pc = next_pc = start_pc; \
145 if (unlikely(pc - start_pc >= bytecode->len)) \
146 goto end; \
147 goto *dispatch[*(filter_opcode_t *) pc];
148
149 #define OP(name) \
150 LABEL_##name
151
152 #define PO \
153 pc = next_pc; \
154 goto *dispatch[*(filter_opcode_t *) pc];
155
156 #define END_OP
157
158 #endif
159
160 int lttng_filter_interpret_bytecode(void *filter_data,
161 const char *filter_stack_data)
162 {
163 struct bytecode_runtime *bytecode = filter_data;
164 void *pc, *next_pc, *start_pc;
165 int ret = -EINVAL;
166 int retval = 0;
167 struct estack _stack;
168 struct estack *stack = &_stack;
169 #ifndef INTERPRETER_USE_SWITCH
170 static void *dispatch[NR_FILTER_OPS] = {
171 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
172
173 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
174
175 /* binary */
176 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
177 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
178 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
179 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
180 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
181 [ FILTER_OP_RSHIFT ] = &&LABEL_FILTER_OP_RSHIFT,
182 [ FILTER_OP_LSHIFT ] = &&LABEL_FILTER_OP_LSHIFT,
183 [ FILTER_OP_BIN_AND ] = &&LABEL_FILTER_OP_BIN_AND,
184 [ FILTER_OP_BIN_OR ] = &&LABEL_FILTER_OP_BIN_OR,
185 [ FILTER_OP_BIN_XOR ] = &&LABEL_FILTER_OP_BIN_XOR,
186
187 /* binary comparators */
188 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
189 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
190 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
191 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
192 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
193 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
194
195 /* string binary comparator */
196 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
197 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
198 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
199 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
200 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
201 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
202
203 /* s64 binary comparator */
204 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
205 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
206 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
207 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
208 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
209 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
210
211 /* double binary comparator */
212 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
213 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
214 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
215 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
216 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
217 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
218
219 /* Mixed S64-double binary comparators */
220 [ FILTER_OP_EQ_DOUBLE_S64 ] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64,
221 [ FILTER_OP_NE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_NE_DOUBLE_S64,
222 [ FILTER_OP_GT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GT_DOUBLE_S64,
223 [ FILTER_OP_LT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LT_DOUBLE_S64,
224 [ FILTER_OP_GE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GE_DOUBLE_S64,
225 [ FILTER_OP_LE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LE_DOUBLE_S64,
226
227 [ FILTER_OP_EQ_S64_DOUBLE ] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE,
228 [ FILTER_OP_NE_S64_DOUBLE ] = &&LABEL_FILTER_OP_NE_S64_DOUBLE,
229 [ FILTER_OP_GT_S64_DOUBLE ] = &&LABEL_FILTER_OP_GT_S64_DOUBLE,
230 [ FILTER_OP_LT_S64_DOUBLE ] = &&LABEL_FILTER_OP_LT_S64_DOUBLE,
231 [ FILTER_OP_GE_S64_DOUBLE ] = &&LABEL_FILTER_OP_GE_S64_DOUBLE,
232 [ FILTER_OP_LE_S64_DOUBLE ] = &&LABEL_FILTER_OP_LE_S64_DOUBLE,
233
234 /* unary */
235 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
236 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
237 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
238 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
239 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
240 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
241 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
242 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
243 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
244
245 /* logical */
246 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
247 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
248
249 /* load */
250 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
251 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
252 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
253 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
254 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
255
256 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
257 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
258 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
259
260 /* cast */
261 [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
262 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
263 [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
264 };
265 #endif /* #ifndef INTERPRETER_USE_SWITCH */
266
267 estack_init(stack);
268
269 START_OP
270
271 OP(FILTER_OP_UNKNOWN):
272 OP(FILTER_OP_LOAD_FIELD_REF):
273 #ifdef INTERPRETER_USE_SWITCH
274 default:
275 #endif /* INTERPRETER_USE_SWITCH */
276 ERR("unknown bytecode op %u\n",
277 (unsigned int) *(filter_opcode_t *) pc);
278 ret = -EINVAL;
279 goto end;
280
281 OP(FILTER_OP_RETURN):
282 retval = !!estack_ax(stack)->u.v;
283 ret = 0;
284 goto end;
285
286 /* binary */
287 OP(FILTER_OP_MUL):
288 OP(FILTER_OP_DIV):
289 OP(FILTER_OP_MOD):
290 OP(FILTER_OP_PLUS):
291 OP(FILTER_OP_MINUS):
292 OP(FILTER_OP_RSHIFT):
293 OP(FILTER_OP_LSHIFT):
294 OP(FILTER_OP_BIN_AND):
295 OP(FILTER_OP_BIN_OR):
296 OP(FILTER_OP_BIN_XOR):
297 ERR("unsupported bytecode op %u\n",
298 (unsigned int) *(filter_opcode_t *) pc);
299 ret = -EINVAL;
300 goto end;
301
302 OP(FILTER_OP_EQ):
303 OP(FILTER_OP_NE):
304 OP(FILTER_OP_GT):
305 OP(FILTER_OP_LT):
306 OP(FILTER_OP_GE):
307 OP(FILTER_OP_LE):
308 ERR("unsupported non-specialized bytecode op %u\n",
309 (unsigned int) *(filter_opcode_t *) pc);
310 ret = -EINVAL;
311 goto end;
312
313 OP(FILTER_OP_EQ_STRING):
314 {
315 int res;
316
317 res = (stack_strcmp(stack, "==") == 0);
318 estack_pop(stack);
319 estack_ax(stack)->u.v = res;
320 estack_ax(stack)->type = REG_S64;
321 next_pc += sizeof(struct binary_op);
322 PO;
323 }
324 OP(FILTER_OP_NE_STRING):
325 {
326 int res;
327
328 res = (stack_strcmp(stack, "!=") != 0);
329 estack_pop(stack);
330 estack_ax(stack)->u.v = res;
331 estack_ax(stack)->type = REG_S64;
332 next_pc += sizeof(struct binary_op);
333 PO;
334 }
335 OP(FILTER_OP_GT_STRING):
336 {
337 int res;
338
339 res = (stack_strcmp(stack, ">") > 0);
340 estack_pop(stack);
341 estack_ax(stack)->u.v = res;
342 estack_ax(stack)->type = REG_S64;
343 next_pc += sizeof(struct binary_op);
344 PO;
345 }
346 OP(FILTER_OP_LT_STRING):
347 {
348 int res;
349
350 res = (stack_strcmp(stack, "<") < 0);
351 estack_pop(stack);
352 estack_ax(stack)->u.v = res;
353 estack_ax(stack)->type = REG_S64;
354 next_pc += sizeof(struct binary_op);
355 PO;
356 }
357 OP(FILTER_OP_GE_STRING):
358 {
359 int res;
360
361 res = (stack_strcmp(stack, ">=") >= 0);
362 estack_pop(stack);
363 estack_ax(stack)->u.v = res;
364 estack_ax(stack)->type = REG_S64;
365 next_pc += sizeof(struct binary_op);
366 PO;
367 }
368 OP(FILTER_OP_LE_STRING):
369 {
370 int res;
371
372 res = (stack_strcmp(stack, "<=") <= 0);
373 estack_pop(stack);
374 estack_ax(stack)->u.v = res;
375 estack_ax(stack)->type = REG_S64;
376 next_pc += sizeof(struct binary_op);
377 PO;
378 }
379
380 OP(FILTER_OP_EQ_S64):
381 {
382 int res;
383
384 res = (estack_bx(stack)->u.v == estack_ax(stack)->u.v);
385 estack_pop(stack);
386 estack_ax(stack)->u.v = res;
387 estack_ax(stack)->type = REG_S64;
388 next_pc += sizeof(struct binary_op);
389 PO;
390 }
391 OP(FILTER_OP_NE_S64):
392 {
393 int res;
394
395 res = (estack_bx(stack)->u.v != estack_ax(stack)->u.v);
396 estack_pop(stack);
397 estack_ax(stack)->u.v = res;
398 estack_ax(stack)->type = REG_S64;
399 next_pc += sizeof(struct binary_op);
400 PO;
401 }
402 OP(FILTER_OP_GT_S64):
403 {
404 int res;
405
406 res = (estack_bx(stack)->u.v > estack_ax(stack)->u.v);
407 estack_pop(stack);
408 estack_ax(stack)->u.v = res;
409 estack_ax(stack)->type = REG_S64;
410 next_pc += sizeof(struct binary_op);
411 PO;
412 }
413 OP(FILTER_OP_LT_S64):
414 {
415 int res;
416
417 res = (estack_bx(stack)->u.v < estack_ax(stack)->u.v);
418 estack_pop(stack);
419 estack_ax(stack)->u.v = res;
420 estack_ax(stack)->type = REG_S64;
421 next_pc += sizeof(struct binary_op);
422 PO;
423 }
424 OP(FILTER_OP_GE_S64):
425 {
426 int res;
427
428 res = (estack_bx(stack)->u.v >= estack_ax(stack)->u.v);
429 estack_pop(stack);
430 estack_ax(stack)->u.v = res;
431 estack_ax(stack)->type = REG_S64;
432 next_pc += sizeof(struct binary_op);
433 PO;
434 }
435 OP(FILTER_OP_LE_S64):
436 {
437 int res;
438
439 res = (estack_bx(stack)->u.v <= estack_ax(stack)->u.v);
440 estack_pop(stack);
441 estack_ax(stack)->u.v = res;
442 estack_ax(stack)->type = REG_S64;
443 next_pc += sizeof(struct binary_op);
444 PO;
445 }
446
447 OP(FILTER_OP_EQ_DOUBLE):
448 {
449 int res;
450
451 res = (estack_bx(stack)->u.d == estack_ax(stack)->u.d);
452 estack_pop(stack);
453 estack_ax(stack)->u.v = res;
454 estack_ax(stack)->type = REG_S64;
455 next_pc += sizeof(struct binary_op);
456 PO;
457 }
458 OP(FILTER_OP_NE_DOUBLE):
459 {
460 int res;
461
462 res = (estack_bx(stack)->u.d != estack_ax(stack)->u.d);
463 estack_pop(stack);
464 estack_ax(stack)->u.v = res;
465 estack_ax(stack)->type = REG_S64;
466 next_pc += sizeof(struct binary_op);
467 PO;
468 }
469 OP(FILTER_OP_GT_DOUBLE):
470 {
471 int res;
472
473 res = (estack_bx(stack)->u.d > estack_ax(stack)->u.d);
474 estack_pop(stack);
475 estack_ax(stack)->u.v = res;
476 estack_ax(stack)->type = REG_S64;
477 next_pc += sizeof(struct binary_op);
478 PO;
479 }
480 OP(FILTER_OP_LT_DOUBLE):
481 {
482 int res;
483
484 res = (estack_bx(stack)->u.d < estack_ax(stack)->u.d);
485 estack_pop(stack);
486 estack_ax(stack)->u.v = res;
487 estack_ax(stack)->type = REG_S64;
488 next_pc += sizeof(struct binary_op);
489 PO;
490 }
491 OP(FILTER_OP_GE_DOUBLE):
492 {
493 int res;
494
495 res = (estack_bx(stack)->u.d >= estack_ax(stack)->u.d);
496 estack_pop(stack);
497 estack_ax(stack)->u.v = res;
498 estack_ax(stack)->type = REG_S64;
499 next_pc += sizeof(struct binary_op);
500 PO;
501 }
502 OP(FILTER_OP_LE_DOUBLE):
503 {
504 int res;
505
506 res = (estack_bx(stack)->u.d <= estack_ax(stack)->u.d);
507 estack_pop(stack);
508 estack_ax(stack)->u.v = res;
509 estack_ax(stack)->type = REG_S64;
510 next_pc += sizeof(struct binary_op);
511 PO;
512 }
513
514 /* Mixed S64-double binary comparators */
515 OP(FILTER_OP_EQ_DOUBLE_S64):
516 {
517 int res;
518
519 res = (estack_bx(stack)->u.d == estack_ax(stack)->u.v);
520 estack_pop(stack);
521 estack_ax(stack)->u.v = res;
522 estack_ax(stack)->type = REG_S64;
523 next_pc += sizeof(struct binary_op);
524 PO;
525 }
526 OP(FILTER_OP_NE_DOUBLE_S64):
527 {
528 int res;
529
530 res = (estack_bx(stack)->u.d != estack_ax(stack)->u.v);
531 estack_pop(stack);
532 estack_ax(stack)->u.v = res;
533 estack_ax(stack)->type = REG_S64;
534 next_pc += sizeof(struct binary_op);
535 PO;
536 }
537 OP(FILTER_OP_GT_DOUBLE_S64):
538 {
539 int res;
540
541 res = (estack_bx(stack)->u.d > estack_ax(stack)->u.v);
542 estack_pop(stack);
543 estack_ax(stack)->u.v = res;
544 estack_ax(stack)->type = REG_S64;
545 next_pc += sizeof(struct binary_op);
546 PO;
547 }
548 OP(FILTER_OP_LT_DOUBLE_S64):
549 {
550 int res;
551
552 res = (estack_bx(stack)->u.d < estack_ax(stack)->u.v);
553 estack_pop(stack);
554 estack_ax(stack)->u.v = res;
555 estack_ax(stack)->type = REG_S64;
556 next_pc += sizeof(struct binary_op);
557 PO;
558 }
559 OP(FILTER_OP_GE_DOUBLE_S64):
560 {
561 int res;
562
563 res = (estack_bx(stack)->u.d >= estack_ax(stack)->u.v);
564 estack_pop(stack);
565 estack_ax(stack)->u.v = res;
566 estack_ax(stack)->type = REG_S64;
567 next_pc += sizeof(struct binary_op);
568 PO;
569 }
570 OP(FILTER_OP_LE_DOUBLE_S64):
571 {
572 int res;
573
574 res = (estack_bx(stack)->u.d <= estack_ax(stack)->u.v);
575 estack_pop(stack);
576 estack_ax(stack)->u.v = res;
577 estack_ax(stack)->type = REG_S64;
578 next_pc += sizeof(struct binary_op);
579 PO;
580 }
581
582 OP(FILTER_OP_EQ_S64_DOUBLE):
583 {
584 int res;
585
586 res = (estack_bx(stack)->u.v == estack_ax(stack)->u.d);
587 estack_pop(stack);
588 estack_ax(stack)->u.v = res;
589 estack_ax(stack)->type = REG_S64;
590 next_pc += sizeof(struct binary_op);
591 PO;
592 }
593 OP(FILTER_OP_NE_S64_DOUBLE):
594 {
595 int res;
596
597 res = (estack_bx(stack)->u.v != estack_ax(stack)->u.d);
598 estack_pop(stack);
599 estack_ax(stack)->u.v = res;
600 estack_ax(stack)->type = REG_S64;
601 next_pc += sizeof(struct binary_op);
602 PO;
603 }
604 OP(FILTER_OP_GT_S64_DOUBLE):
605 {
606 int res;
607
608 res = (estack_bx(stack)->u.v > estack_ax(stack)->u.d);
609 estack_pop(stack);
610 estack_ax(stack)->u.v = res;
611 estack_ax(stack)->type = REG_S64;
612 next_pc += sizeof(struct binary_op);
613 PO;
614 }
615 OP(FILTER_OP_LT_S64_DOUBLE):
616 {
617 int res;
618
619 res = (estack_bx(stack)->u.v < estack_ax(stack)->u.d);
620 estack_pop(stack);
621 estack_ax(stack)->u.v = res;
622 estack_ax(stack)->type = REG_S64;
623 next_pc += sizeof(struct binary_op);
624 PO;
625 }
626 OP(FILTER_OP_GE_S64_DOUBLE):
627 {
628 int res;
629
630 res = (estack_bx(stack)->u.v >= estack_ax(stack)->u.d);
631 estack_pop(stack);
632 estack_ax(stack)->u.v = res;
633 estack_ax(stack)->type = REG_S64;
634 next_pc += sizeof(struct binary_op);
635 PO;
636 }
637 OP(FILTER_OP_LE_S64_DOUBLE):
638 {
639 int res;
640
641 res = (estack_bx(stack)->u.v <= estack_ax(stack)->u.d);
642 estack_pop(stack);
643 estack_ax(stack)->u.v = res;
644 estack_ax(stack)->type = REG_S64;
645 next_pc += sizeof(struct binary_op);
646 PO;
647 }
648
649 /* unary */
650 OP(FILTER_OP_UNARY_PLUS):
651 OP(FILTER_OP_UNARY_MINUS):
652 OP(FILTER_OP_UNARY_NOT):
653 ERR("unsupported non-specialized bytecode op %u\n",
654 (unsigned int) *(filter_opcode_t *) pc);
655 ret = -EINVAL;
656 goto end;
657
658
659 OP(FILTER_OP_UNARY_PLUS_S64):
660 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
661 {
662 next_pc += sizeof(struct unary_op);
663 PO;
664 }
665 OP(FILTER_OP_UNARY_MINUS_S64):
666 {
667 estack_ax(stack)->u.v = -estack_ax(stack)->u.v;
668 next_pc += sizeof(struct unary_op);
669 PO;
670 }
671 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
672 {
673 estack_ax(stack)->u.d = -estack_ax(stack)->u.d;
674 next_pc += sizeof(struct unary_op);
675 PO;
676 }
677 OP(FILTER_OP_UNARY_NOT_S64):
678 {
679 estack_ax(stack)->u.v = !estack_ax(stack)->u.v;
680 next_pc += sizeof(struct unary_op);
681 PO;
682 }
683 OP(FILTER_OP_UNARY_NOT_DOUBLE):
684 {
685 estack_ax(stack)->u.d = !estack_ax(stack)->u.d;
686 next_pc += sizeof(struct unary_op);
687 PO;
688 }
689
690 /* logical */
691 OP(FILTER_OP_AND):
692 {
693 struct logical_op *insn = (struct logical_op *) pc;
694
695 /* If AX is 0, skip and evaluate to 0 */
696 if (unlikely(estack_ax(stack)->u.v == 0)) {
697 dbg_printf("Jumping to bytecode offset %u\n",
698 (unsigned int) insn->skip_offset);
699 next_pc = start_pc + insn->skip_offset;
700 } else {
701 /* Pop 1 when jump not taken */
702 estack_pop(stack);
703 next_pc += sizeof(struct logical_op);
704 }
705 PO;
706 }
707 OP(FILTER_OP_OR):
708 {
709 struct logical_op *insn = (struct logical_op *) pc;
710
711 /* If AX is nonzero, skip and evaluate to 1 */
712
713 if (unlikely(estack_ax(stack)->u.v != 0)) {
714 estack_ax(stack)->u.v = 1;
715 dbg_printf("Jumping to bytecode offset %u\n",
716 (unsigned int) insn->skip_offset);
717 next_pc = start_pc + insn->skip_offset;
718 } else {
719 /* Pop 1 when jump not taken */
720 estack_pop(stack);
721 next_pc += sizeof(struct logical_op);
722 }
723 PO;
724 }
725
726
727 /* load */
728 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
729 {
730 struct load_op *insn = (struct load_op *) pc;
731 struct field_ref *ref = (struct field_ref *) insn->data;
732
733 dbg_printf("load field ref offset %u type string\n",
734 ref->offset);
735 estack_push(stack);
736 estack_ax(stack)->u.s.str =
737 *(const char * const *) &filter_stack_data[ref->offset];
738 if (unlikely(!estack_ax(stack)->u.s.str)) {
739 dbg_printf("Filter warning: loading a NULL string.\n");
740 ret = -EINVAL;
741 goto end;
742 }
743 estack_ax(stack)->type = REG_STRING;
744 estack_ax(stack)->u.s.seq_len = UINT_MAX;
745 estack_ax(stack)->u.s.literal = 0;
746 dbg_printf("ref load string %s\n", estack_ax(stack)->u.s.str);
747 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
748 PO;
749 }
750
751 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
752 {
753 struct load_op *insn = (struct load_op *) pc;
754 struct field_ref *ref = (struct field_ref *) insn->data;
755
756 dbg_printf("load field ref offset %u type sequence\n",
757 ref->offset);
758 estack_push(stack);
759 estack_ax(stack)->u.s.seq_len =
760 *(unsigned long *) &filter_stack_data[ref->offset];
761 estack_ax(stack)->u.s.str =
762 *(const char **) (&filter_stack_data[ref->offset
763 + sizeof(unsigned long)]);
764 if (unlikely(!estack_ax(stack)->u.s.str)) {
765 dbg_printf("Filter warning: loading a NULL sequence.\n");
766 ret = -EINVAL;
767 goto end;
768 }
769 estack_ax(stack)->type = REG_STRING;
770 estack_ax(stack)->u.s.literal = 0;
771 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
772 PO;
773 }
774
775 OP(FILTER_OP_LOAD_FIELD_REF_S64):
776 {
777 struct load_op *insn = (struct load_op *) pc;
778 struct field_ref *ref = (struct field_ref *) insn->data;
779
780 dbg_printf("load field ref offset %u type s64\n",
781 ref->offset);
782 estack_push(stack);
783 memcpy(&estack_ax(stack)->u.v, &filter_stack_data[ref->offset],
784 sizeof(struct literal_numeric));
785 estack_ax(stack)->type = REG_S64;
786 dbg_printf("ref load s64 %" PRIi64 "\n", estack_ax(stack)->u.v);
787 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
788 PO;
789 }
790
791 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
792 {
793 struct load_op *insn = (struct load_op *) pc;
794 struct field_ref *ref = (struct field_ref *) insn->data;
795
796 dbg_printf("load field ref offset %u type double\n",
797 ref->offset);
798 estack_push(stack);
799 memcpy(&estack_ax(stack)->u.d, &filter_stack_data[ref->offset],
800 sizeof(struct literal_double));
801 estack_ax(stack)->type = REG_DOUBLE;
802 dbg_printf("ref load double %g\n", estack_ax(stack)->u.d);
803 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
804 PO;
805 }
806
807 OP(FILTER_OP_LOAD_STRING):
808 {
809 struct load_op *insn = (struct load_op *) pc;
810
811 dbg_printf("load string %s\n", insn->data);
812 estack_push(stack);
813 estack_ax(stack)->type = REG_STRING;
814 estack_ax(stack)->u.s.str = insn->data;
815 estack_ax(stack)->u.s.seq_len = UINT_MAX;
816 estack_ax(stack)->u.s.literal = 1;
817 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
818 PO;
819 }
820
821 OP(FILTER_OP_LOAD_S64):
822 {
823 struct load_op *insn = (struct load_op *) pc;
824
825 estack_push(stack);
826 memcpy(&estack_ax(stack)->u.v, insn->data,
827 sizeof(struct literal_numeric));
828 dbg_printf("load s64 %" PRIi64 "\n", estack_ax(stack)->u.v);
829 estack_ax(stack)->type = REG_S64;
830 next_pc += sizeof(struct load_op)
831 + sizeof(struct literal_numeric);
832 PO;
833 }
834
835 OP(FILTER_OP_LOAD_DOUBLE):
836 {
837 struct load_op *insn = (struct load_op *) pc;
838
839 estack_push(stack);
840 memcpy(&estack_ax(stack)->u.d, insn->data,
841 sizeof(struct literal_double));
842 dbg_printf("load s64 %g\n", estack_ax(stack)->u.d);
843 estack_ax(stack)->type = REG_DOUBLE;
844 next_pc += sizeof(struct load_op)
845 + sizeof(struct literal_double);
846 PO;
847 }
848
849 /* cast */
850 OP(FILTER_OP_CAST_TO_S64):
851 ERR("unsupported non-specialized bytecode op %u\n",
852 (unsigned int) *(filter_opcode_t *) pc);
853 ret = -EINVAL;
854 goto end;
855
856 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
857 {
858 estack_ax(stack)->u.v = (int64_t) estack_ax(stack)->u.d;
859 estack_ax(stack)->type = REG_S64;
860 next_pc += sizeof(struct cast_op);
861 PO;
862 }
863
864 OP(FILTER_OP_CAST_NOP):
865 {
866 next_pc += sizeof(struct cast_op);
867 PO;
868 }
869
870 END_OP
871 end:
872 /* return 0 (discard) on error */
873 if (ret)
874 return 0;
875 return retval;
876 }
877
878 #undef START_OP
879 #undef OP
880 #undef PO
881 #undef END_OP
This page took 0.047457 seconds and 5 git commands to generate.