Filter: specialize double-s64 binary comparators
[lttng-ust.git] / liblttng-ust / lttng-filter-interpreter.c
CommitLineData
97b58163
MD
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
31static
32int 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
51static
0305960f 52int stack_strcmp(struct estack *stack, const char *cmp_type)
97b58163 53{
0305960f 54 const char *p = estack_bx(stack)->u.s.str, *q = estack_ax(stack)->u.s.str;
97b58163
MD
55 int ret;
56 int diff;
57
58 for (;;) {
59 int escaped_r0 = 0;
60
0305960f
MD
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')
97b58163
MD
63 diff = 0;
64 else
65 diff = -1;
66 break;
67 }
0305960f
MD
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')
97b58163
MD
70 diff = 0;
71 else
72 diff = 1;
73 break;
74 }
0305960f 75 if (estack_bx(stack)->u.s.literal) {
97b58163
MD
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 }
0305960f 84 if (estack_ax(stack)->u.s.literal) {
97b58163
MD
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
108int 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) \
150LABEL_##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
160int 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;
0305960f
MD
167 struct estack _stack;
168 struct estack *stack = &_stack;
97b58163
MD
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
dbea82ec
MD
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
97b58163
MD
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
0305960f
MD
267 estack_init(stack);
268
97b58163
MD
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):
0305960f 282 retval = !!estack_ax(stack)->u.v;
97b58163
MD
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 {
0305960f
MD
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;
97b58163
MD
321 next_pc += sizeof(struct binary_op);
322 PO;
323 }
324 OP(FILTER_OP_NE_STRING):
325 {
0305960f
MD
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;
97b58163
MD
332 next_pc += sizeof(struct binary_op);
333 PO;
334 }
335 OP(FILTER_OP_GT_STRING):
336 {
0305960f
MD
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;
97b58163
MD
343 next_pc += sizeof(struct binary_op);
344 PO;
345 }
346 OP(FILTER_OP_LT_STRING):
347 {
0305960f
MD
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;
97b58163
MD
354 next_pc += sizeof(struct binary_op);
355 PO;
356 }
357 OP(FILTER_OP_GE_STRING):
358 {
0305960f
MD
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;
97b58163
MD
365 next_pc += sizeof(struct binary_op);
366 PO;
367 }
368 OP(FILTER_OP_LE_STRING):
369 {
0305960f
MD
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;
97b58163
MD
376 next_pc += sizeof(struct binary_op);
377 PO;
378 }
379
380 OP(FILTER_OP_EQ_S64):
381 {
0305960f
MD
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;
97b58163
MD
388 next_pc += sizeof(struct binary_op);
389 PO;
390 }
391 OP(FILTER_OP_NE_S64):
392 {
0305960f
MD
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;
97b58163
MD
399 next_pc += sizeof(struct binary_op);
400 PO;
401 }
402 OP(FILTER_OP_GT_S64):
403 {
0305960f
MD
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;
97b58163
MD
410 next_pc += sizeof(struct binary_op);
411 PO;
412 }
413 OP(FILTER_OP_LT_S64):
414 {
0305960f
MD
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;
97b58163
MD
421 next_pc += sizeof(struct binary_op);
422 PO;
423 }
424 OP(FILTER_OP_GE_S64):
425 {
0305960f
MD
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;
97b58163
MD
432 next_pc += sizeof(struct binary_op);
433 PO;
434 }
435 OP(FILTER_OP_LE_S64):
436 {
0305960f
MD
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;
97b58163
MD
443 next_pc += sizeof(struct binary_op);
444 PO;
445 }
446
447 OP(FILTER_OP_EQ_DOUBLE):
448 {
0305960f
MD
449 int res;
450
dbea82ec 451 res = (estack_bx(stack)->u.d == estack_ax(stack)->u.d);
0305960f
MD
452 estack_pop(stack);
453 estack_ax(stack)->u.v = res;
454 estack_ax(stack)->type = REG_S64;
97b58163
MD
455 next_pc += sizeof(struct binary_op);
456 PO;
457 }
458 OP(FILTER_OP_NE_DOUBLE):
459 {
0305960f
MD
460 int res;
461
dbea82ec 462 res = (estack_bx(stack)->u.d != estack_ax(stack)->u.d);
0305960f
MD
463 estack_pop(stack);
464 estack_ax(stack)->u.v = res;
465 estack_ax(stack)->type = REG_S64;
97b58163
MD
466 next_pc += sizeof(struct binary_op);
467 PO;
468 }
469 OP(FILTER_OP_GT_DOUBLE):
470 {
0305960f
MD
471 int res;
472
dbea82ec 473 res = (estack_bx(stack)->u.d > estack_ax(stack)->u.d);
0305960f
MD
474 estack_pop(stack);
475 estack_ax(stack)->u.v = res;
476 estack_ax(stack)->type = REG_S64;
97b58163
MD
477 next_pc += sizeof(struct binary_op);
478 PO;
479 }
480 OP(FILTER_OP_LT_DOUBLE):
481 {
0305960f
MD
482 int res;
483
dbea82ec 484 res = (estack_bx(stack)->u.d < estack_ax(stack)->u.d);
0305960f
MD
485 estack_pop(stack);
486 estack_ax(stack)->u.v = res;
487 estack_ax(stack)->type = REG_S64;
97b58163
MD
488 next_pc += sizeof(struct binary_op);
489 PO;
490 }
491 OP(FILTER_OP_GE_DOUBLE):
492 {
0305960f
MD
493 int res;
494
dbea82ec 495 res = (estack_bx(stack)->u.d >= estack_ax(stack)->u.d);
0305960f
MD
496 estack_pop(stack);
497 estack_ax(stack)->u.v = res;
498 estack_ax(stack)->type = REG_S64;
97b58163
MD
499 next_pc += sizeof(struct binary_op);
500 PO;
501 }
502 OP(FILTER_OP_LE_DOUBLE):
503 {
0305960f
MD
504 int res;
505
dbea82ec
MD
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);
0305960f
MD
642 estack_pop(stack);
643 estack_ax(stack)->u.v = res;
644 estack_ax(stack)->type = REG_S64;
97b58163
MD
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 {
0305960f 667 estack_ax(stack)->u.v = -estack_ax(stack)->u.v;
97b58163
MD
668 next_pc += sizeof(struct unary_op);
669 PO;
670 }
671 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
672 {
0305960f 673 estack_ax(stack)->u.d = -estack_ax(stack)->u.d;
97b58163
MD
674 next_pc += sizeof(struct unary_op);
675 PO;
676 }
677 OP(FILTER_OP_UNARY_NOT_S64):
678 {
0305960f 679 estack_ax(stack)->u.v = !estack_ax(stack)->u.v;
97b58163
MD
680 next_pc += sizeof(struct unary_op);
681 PO;
682 }
683 OP(FILTER_OP_UNARY_NOT_DOUBLE):
684 {
0305960f 685 estack_ax(stack)->u.d = !estack_ax(stack)->u.d;
97b58163
MD
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
0305960f
MD
695 /* If AX is 0, skip and evaluate to 0 */
696 if (unlikely(estack_ax(stack)->u.v == 0)) {
97b58163
MD
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 {
71c1ceeb
MD
701 /* Pop 1 when jump not taken */
702 estack_pop(stack);
97b58163
MD
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
0305960f 711 /* If AX is nonzero, skip and evaluate to 1 */
97b58163 712
0305960f
MD
713 if (unlikely(estack_ax(stack)->u.v != 0)) {
714 estack_ax(stack)->u.v = 1;
97b58163
MD
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 {
71c1ceeb
MD
719 /* Pop 1 when jump not taken */
720 estack_pop(stack);
97b58163
MD
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);
0305960f
MD
735 estack_push(stack);
736 estack_ax(stack)->u.s.str =
97b58163 737 *(const char * const *) &filter_stack_data[ref->offset];
0305960f 738 if (unlikely(!estack_ax(stack)->u.s.str)) {
97b58163
MD
739 dbg_printf("Filter warning: loading a NULL string.\n");
740 ret = -EINVAL;
741 goto end;
742 }
0305960f
MD
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);
97b58163
MD
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);
0305960f
MD
758 estack_push(stack);
759 estack_ax(stack)->u.s.seq_len =
97b58163 760 *(unsigned long *) &filter_stack_data[ref->offset];
0305960f 761 estack_ax(stack)->u.s.str =
97b58163
MD
762 *(const char **) (&filter_stack_data[ref->offset
763 + sizeof(unsigned long)]);
0305960f 764 if (unlikely(!estack_ax(stack)->u.s.str)) {
97b58163
MD
765 dbg_printf("Filter warning: loading a NULL sequence.\n");
766 ret = -EINVAL;
767 goto end;
768 }
0305960f
MD
769 estack_ax(stack)->type = REG_STRING;
770 estack_ax(stack)->u.s.literal = 0;
97b58163
MD
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);
0305960f
MD
782 estack_push(stack);
783 memcpy(&estack_ax(stack)->u.v, &filter_stack_data[ref->offset],
97b58163 784 sizeof(struct literal_numeric));
0305960f
MD
785 estack_ax(stack)->type = REG_S64;
786 dbg_printf("ref load s64 %" PRIi64 "\n", estack_ax(stack)->u.v);
97b58163
MD
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);
0305960f
MD
798 estack_push(stack);
799 memcpy(&estack_ax(stack)->u.d, &filter_stack_data[ref->offset],
97b58163 800 sizeof(struct literal_double));
0305960f
MD
801 estack_ax(stack)->type = REG_DOUBLE;
802 dbg_printf("ref load double %g\n", estack_ax(stack)->u.d);
97b58163
MD
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);
0305960f
MD
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;
97b58163
MD
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
0305960f
MD
825 estack_push(stack);
826 memcpy(&estack_ax(stack)->u.v, insn->data,
97b58163 827 sizeof(struct literal_numeric));
0305960f
MD
828 dbg_printf("load s64 %" PRIi64 "\n", estack_ax(stack)->u.v);
829 estack_ax(stack)->type = REG_S64;
97b58163
MD
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
0305960f
MD
839 estack_push(stack);
840 memcpy(&estack_ax(stack)->u.d, insn->data,
97b58163 841 sizeof(struct literal_double));
0305960f
MD
842 dbg_printf("load s64 %g\n", estack_ax(stack)->u.d);
843 estack_ax(stack)->type = REG_DOUBLE;
97b58163
MD
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 {
0305960f
MD
858 estack_ax(stack)->u.v = (int64_t) estack_ax(stack)->u.d;
859 estack_ax(stack)->type = REG_S64;
97b58163
MD
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
871end:
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.058369 seconds and 4 git commands to generate.