2 * lttng-filter-interpreter.c
4 * LTTng UST filter interpreter.
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"
27 * -2: unknown escape char.
32 int parse_char(const char **p
)
52 int stack_strcmp(struct estack
*stack
, int top
, const char *cmp_type
)
54 const char *p
= estack_bx(stack
, top
)->u
.s
.str
, *q
= estack_ax(stack
, top
)->u
.s
.str
;
61 if (unlikely(p
- estack_bx(stack
, top
)->u
.s
.str
> estack_bx(stack
, top
)->u
.s
.seq_len
|| *p
== '\0')) {
62 if (q
- estack_ax(stack
, top
)->u
.s
.str
> estack_ax(stack
, top
)->u
.s
.seq_len
|| *q
== '\0')
68 if (unlikely(q
- estack_ax(stack
, top
)->u
.s
.str
> estack_ax(stack
, top
)->u
.s
.seq_len
|| *q
== '\0')) {
69 if (p
- estack_bx(stack
, top
)->u
.s
.str
> estack_bx(stack
, top
)->u
.s
.seq_len
|| *p
== '\0')
75 if (estack_bx(stack
, top
)->u
.s
.literal
) {
79 } else if (ret
== -2) {
82 /* else compare both char */
84 if (estack_ax(stack
, top
)->u
.s
.literal
) {
88 } else if (ret
== -2) {
108 uint64_t lttng_filter_false(void *filter_data
,
109 const char *filter_stack_data
)
114 #ifdef INTERPRETER_USE_SWITCH
117 * Fallback for compilers that do not support taking address of labels.
121 start_pc = &bytecode->data[0]; \
122 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
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) {
129 #define OP(name) case name
139 * Dispatch-table based interpreter.
143 start_pc = &bytecode->data[0]; \
144 pc = next_pc = start_pc; \
145 if (unlikely(pc - start_pc >= bytecode->len)) \
147 goto *dispatch[*(filter_opcode_t *) pc];
154 goto *dispatch[*(filter_opcode_t *) pc];
161 * Return 0 (discard), or raise the 0x1 flag (log event).
162 * Currently, other flags are kept for future extensions and have no
165 uint64_t lttng_filter_interpret_bytecode(void *filter_data
,
166 const char *filter_stack_data
)
168 struct bytecode_runtime
*bytecode
= filter_data
;
169 void *pc
, *next_pc
, *start_pc
;
172 struct estack _stack
;
173 struct estack
*stack
= &_stack
;
174 register int64_t ax
= 0, bx
= 0;
175 register int top
= FILTER_STACK_EMPTY
;
176 #ifndef INTERPRETER_USE_SWITCH
177 static void *dispatch
[NR_FILTER_OPS
] = {
178 [ FILTER_OP_UNKNOWN
] = &&LABEL_FILTER_OP_UNKNOWN
,
180 [ FILTER_OP_RETURN
] = &&LABEL_FILTER_OP_RETURN
,
183 [ FILTER_OP_MUL
] = &&LABEL_FILTER_OP_MUL
,
184 [ FILTER_OP_DIV
] = &&LABEL_FILTER_OP_DIV
,
185 [ FILTER_OP_MOD
] = &&LABEL_FILTER_OP_MOD
,
186 [ FILTER_OP_PLUS
] = &&LABEL_FILTER_OP_PLUS
,
187 [ FILTER_OP_MINUS
] = &&LABEL_FILTER_OP_MINUS
,
188 [ FILTER_OP_RSHIFT
] = &&LABEL_FILTER_OP_RSHIFT
,
189 [ FILTER_OP_LSHIFT
] = &&LABEL_FILTER_OP_LSHIFT
,
190 [ FILTER_OP_BIN_AND
] = &&LABEL_FILTER_OP_BIN_AND
,
191 [ FILTER_OP_BIN_OR
] = &&LABEL_FILTER_OP_BIN_OR
,
192 [ FILTER_OP_BIN_XOR
] = &&LABEL_FILTER_OP_BIN_XOR
,
194 /* binary comparators */
195 [ FILTER_OP_EQ
] = &&LABEL_FILTER_OP_EQ
,
196 [ FILTER_OP_NE
] = &&LABEL_FILTER_OP_NE
,
197 [ FILTER_OP_GT
] = &&LABEL_FILTER_OP_GT
,
198 [ FILTER_OP_LT
] = &&LABEL_FILTER_OP_LT
,
199 [ FILTER_OP_GE
] = &&LABEL_FILTER_OP_GE
,
200 [ FILTER_OP_LE
] = &&LABEL_FILTER_OP_LE
,
202 /* string binary comparator */
203 [ FILTER_OP_EQ_STRING
] = &&LABEL_FILTER_OP_EQ_STRING
,
204 [ FILTER_OP_NE_STRING
] = &&LABEL_FILTER_OP_NE_STRING
,
205 [ FILTER_OP_GT_STRING
] = &&LABEL_FILTER_OP_GT_STRING
,
206 [ FILTER_OP_LT_STRING
] = &&LABEL_FILTER_OP_LT_STRING
,
207 [ FILTER_OP_GE_STRING
] = &&LABEL_FILTER_OP_GE_STRING
,
208 [ FILTER_OP_LE_STRING
] = &&LABEL_FILTER_OP_LE_STRING
,
210 /* s64 binary comparator */
211 [ FILTER_OP_EQ_S64
] = &&LABEL_FILTER_OP_EQ_S64
,
212 [ FILTER_OP_NE_S64
] = &&LABEL_FILTER_OP_NE_S64
,
213 [ FILTER_OP_GT_S64
] = &&LABEL_FILTER_OP_GT_S64
,
214 [ FILTER_OP_LT_S64
] = &&LABEL_FILTER_OP_LT_S64
,
215 [ FILTER_OP_GE_S64
] = &&LABEL_FILTER_OP_GE_S64
,
216 [ FILTER_OP_LE_S64
] = &&LABEL_FILTER_OP_LE_S64
,
218 /* double binary comparator */
219 [ FILTER_OP_EQ_DOUBLE
] = &&LABEL_FILTER_OP_EQ_DOUBLE
,
220 [ FILTER_OP_NE_DOUBLE
] = &&LABEL_FILTER_OP_NE_DOUBLE
,
221 [ FILTER_OP_GT_DOUBLE
] = &&LABEL_FILTER_OP_GT_DOUBLE
,
222 [ FILTER_OP_LT_DOUBLE
] = &&LABEL_FILTER_OP_LT_DOUBLE
,
223 [ FILTER_OP_GE_DOUBLE
] = &&LABEL_FILTER_OP_GE_DOUBLE
,
224 [ FILTER_OP_LE_DOUBLE
] = &&LABEL_FILTER_OP_LE_DOUBLE
,
226 /* Mixed S64-double binary comparators */
227 [ FILTER_OP_EQ_DOUBLE_S64
] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64
,
228 [ FILTER_OP_NE_DOUBLE_S64
] = &&LABEL_FILTER_OP_NE_DOUBLE_S64
,
229 [ FILTER_OP_GT_DOUBLE_S64
] = &&LABEL_FILTER_OP_GT_DOUBLE_S64
,
230 [ FILTER_OP_LT_DOUBLE_S64
] = &&LABEL_FILTER_OP_LT_DOUBLE_S64
,
231 [ FILTER_OP_GE_DOUBLE_S64
] = &&LABEL_FILTER_OP_GE_DOUBLE_S64
,
232 [ FILTER_OP_LE_DOUBLE_S64
] = &&LABEL_FILTER_OP_LE_DOUBLE_S64
,
234 [ FILTER_OP_EQ_S64_DOUBLE
] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE
,
235 [ FILTER_OP_NE_S64_DOUBLE
] = &&LABEL_FILTER_OP_NE_S64_DOUBLE
,
236 [ FILTER_OP_GT_S64_DOUBLE
] = &&LABEL_FILTER_OP_GT_S64_DOUBLE
,
237 [ FILTER_OP_LT_S64_DOUBLE
] = &&LABEL_FILTER_OP_LT_S64_DOUBLE
,
238 [ FILTER_OP_GE_S64_DOUBLE
] = &&LABEL_FILTER_OP_GE_S64_DOUBLE
,
239 [ FILTER_OP_LE_S64_DOUBLE
] = &&LABEL_FILTER_OP_LE_S64_DOUBLE
,
242 [ FILTER_OP_UNARY_PLUS
] = &&LABEL_FILTER_OP_UNARY_PLUS
,
243 [ FILTER_OP_UNARY_MINUS
] = &&LABEL_FILTER_OP_UNARY_MINUS
,
244 [ FILTER_OP_UNARY_NOT
] = &&LABEL_FILTER_OP_UNARY_NOT
,
245 [ FILTER_OP_UNARY_PLUS_S64
] = &&LABEL_FILTER_OP_UNARY_PLUS_S64
,
246 [ FILTER_OP_UNARY_MINUS_S64
] = &&LABEL_FILTER_OP_UNARY_MINUS_S64
,
247 [ FILTER_OP_UNARY_NOT_S64
] = &&LABEL_FILTER_OP_UNARY_NOT_S64
,
248 [ FILTER_OP_UNARY_PLUS_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE
,
249 [ FILTER_OP_UNARY_MINUS_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE
,
250 [ FILTER_OP_UNARY_NOT_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE
,
253 [ FILTER_OP_AND
] = &&LABEL_FILTER_OP_AND
,
254 [ FILTER_OP_OR
] = &&LABEL_FILTER_OP_OR
,
257 [ FILTER_OP_LOAD_FIELD_REF
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF
,
258 [ FILTER_OP_LOAD_FIELD_REF_STRING
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING
,
259 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE
,
260 [ FILTER_OP_LOAD_FIELD_REF_S64
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64
,
261 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE
,
263 [ FILTER_OP_LOAD_STRING
] = &&LABEL_FILTER_OP_LOAD_STRING
,
264 [ FILTER_OP_LOAD_S64
] = &&LABEL_FILTER_OP_LOAD_S64
,
265 [ FILTER_OP_LOAD_DOUBLE
] = &&LABEL_FILTER_OP_LOAD_DOUBLE
,
268 [ FILTER_OP_CAST_TO_S64
] = &&LABEL_FILTER_OP_CAST_TO_S64
,
269 [ FILTER_OP_CAST_DOUBLE_TO_S64
] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64
,
270 [ FILTER_OP_CAST_NOP
] = &&LABEL_FILTER_OP_CAST_NOP
,
272 #endif /* #ifndef INTERPRETER_USE_SWITCH */
276 OP(FILTER_OP_UNKNOWN
):
277 OP(FILTER_OP_LOAD_FIELD_REF
):
278 #ifdef INTERPRETER_USE_SWITCH
280 #endif /* INTERPRETER_USE_SWITCH */
281 ERR("unknown bytecode op %u\n",
282 (unsigned int) *(filter_opcode_t
*) pc
);
286 OP(FILTER_OP_RETURN
):
287 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
288 retval
= !!estack_ax_v
;
298 OP(FILTER_OP_RSHIFT
):
299 OP(FILTER_OP_LSHIFT
):
300 OP(FILTER_OP_BIN_AND
):
301 OP(FILTER_OP_BIN_OR
):
302 OP(FILTER_OP_BIN_XOR
):
303 ERR("unsupported bytecode op %u\n",
304 (unsigned int) *(filter_opcode_t
*) pc
);
314 ERR("unsupported non-specialized bytecode op %u\n",
315 (unsigned int) *(filter_opcode_t
*) pc
);
319 OP(FILTER_OP_EQ_STRING
):
323 res
= (stack_strcmp(stack
, top
, "==") == 0);
324 estack_pop(stack
, top
, ax
, bx
);
326 next_pc
+= sizeof(struct binary_op
);
329 OP(FILTER_OP_NE_STRING
):
333 res
= (stack_strcmp(stack
, top
, "!=") != 0);
334 estack_pop(stack
, top
, ax
, bx
);
336 next_pc
+= sizeof(struct binary_op
);
339 OP(FILTER_OP_GT_STRING
):
343 res
= (stack_strcmp(stack
, top
, ">") > 0);
344 estack_pop(stack
, top
, ax
, bx
);
346 next_pc
+= sizeof(struct binary_op
);
349 OP(FILTER_OP_LT_STRING
):
353 res
= (stack_strcmp(stack
, top
, "<") < 0);
354 estack_pop(stack
, top
, ax
, bx
);
356 next_pc
+= sizeof(struct binary_op
);
359 OP(FILTER_OP_GE_STRING
):
363 res
= (stack_strcmp(stack
, top
, ">=") >= 0);
364 estack_pop(stack
, top
, ax
, bx
);
366 next_pc
+= sizeof(struct binary_op
);
369 OP(FILTER_OP_LE_STRING
):
373 res
= (stack_strcmp(stack
, top
, "<=") <= 0);
374 estack_pop(stack
, top
, ax
, bx
);
376 next_pc
+= sizeof(struct binary_op
);
380 OP(FILTER_OP_EQ_S64
):
384 res
= (estack_bx_v
== estack_ax_v
);
385 estack_pop(stack
, top
, ax
, bx
);
387 next_pc
+= sizeof(struct binary_op
);
390 OP(FILTER_OP_NE_S64
):
394 res
= (estack_bx_v
!= estack_ax_v
);
395 estack_pop(stack
, top
, ax
, bx
);
397 next_pc
+= sizeof(struct binary_op
);
400 OP(FILTER_OP_GT_S64
):
404 res
= (estack_bx_v
> estack_ax_v
);
405 estack_pop(stack
, top
, ax
, bx
);
407 next_pc
+= sizeof(struct binary_op
);
410 OP(FILTER_OP_LT_S64
):
414 res
= (estack_bx_v
< estack_ax_v
);
415 estack_pop(stack
, top
, ax
, bx
);
417 next_pc
+= sizeof(struct binary_op
);
420 OP(FILTER_OP_GE_S64
):
424 res
= (estack_bx_v
>= estack_ax_v
);
425 estack_pop(stack
, top
, ax
, bx
);
427 next_pc
+= sizeof(struct binary_op
);
430 OP(FILTER_OP_LE_S64
):
434 res
= (estack_bx_v
<= estack_ax_v
);
435 estack_pop(stack
, top
, ax
, bx
);
437 next_pc
+= sizeof(struct binary_op
);
441 OP(FILTER_OP_EQ_DOUBLE
):
445 res
= (estack_bx(stack
, top
)->u
.d
== estack_ax(stack
, top
)->u
.d
);
446 estack_pop(stack
, top
, ax
, bx
);
448 next_pc
+= sizeof(struct binary_op
);
451 OP(FILTER_OP_NE_DOUBLE
):
455 res
= (estack_bx(stack
, top
)->u
.d
!= estack_ax(stack
, top
)->u
.d
);
456 estack_pop(stack
, top
, ax
, bx
);
458 next_pc
+= sizeof(struct binary_op
);
461 OP(FILTER_OP_GT_DOUBLE
):
465 res
= (estack_bx(stack
, top
)->u
.d
> estack_ax(stack
, top
)->u
.d
);
466 estack_pop(stack
, top
, ax
, bx
);
468 next_pc
+= sizeof(struct binary_op
);
471 OP(FILTER_OP_LT_DOUBLE
):
475 res
= (estack_bx(stack
, top
)->u
.d
< estack_ax(stack
, top
)->u
.d
);
476 estack_pop(stack
, top
, ax
, bx
);
478 next_pc
+= sizeof(struct binary_op
);
481 OP(FILTER_OP_GE_DOUBLE
):
485 res
= (estack_bx(stack
, top
)->u
.d
>= estack_ax(stack
, top
)->u
.d
);
486 estack_pop(stack
, top
, ax
, bx
);
488 next_pc
+= sizeof(struct binary_op
);
491 OP(FILTER_OP_LE_DOUBLE
):
495 res
= (estack_bx(stack
, top
)->u
.d
<= estack_ax(stack
, top
)->u
.d
);
496 estack_pop(stack
, top
, ax
, bx
);
498 next_pc
+= sizeof(struct binary_op
);
502 /* Mixed S64-double binary comparators */
503 OP(FILTER_OP_EQ_DOUBLE_S64
):
507 res
= (estack_bx(stack
, top
)->u
.d
== estack_ax_v
);
508 estack_pop(stack
, top
, ax
, bx
);
510 next_pc
+= sizeof(struct binary_op
);
513 OP(FILTER_OP_NE_DOUBLE_S64
):
517 res
= (estack_bx(stack
, top
)->u
.d
!= estack_ax_v
);
518 estack_pop(stack
, top
, ax
, bx
);
520 next_pc
+= sizeof(struct binary_op
);
523 OP(FILTER_OP_GT_DOUBLE_S64
):
527 res
= (estack_bx(stack
, top
)->u
.d
> estack_ax_v
);
528 estack_pop(stack
, top
, ax
, bx
);
530 next_pc
+= sizeof(struct binary_op
);
533 OP(FILTER_OP_LT_DOUBLE_S64
):
537 res
= (estack_bx(stack
, top
)->u
.d
< estack_ax_v
);
538 estack_pop(stack
, top
, ax
, bx
);
540 next_pc
+= sizeof(struct binary_op
);
543 OP(FILTER_OP_GE_DOUBLE_S64
):
547 res
= (estack_bx(stack
, top
)->u
.d
>= estack_ax_v
);
548 estack_pop(stack
, top
, ax
, bx
);
550 next_pc
+= sizeof(struct binary_op
);
553 OP(FILTER_OP_LE_DOUBLE_S64
):
557 res
= (estack_bx(stack
, top
)->u
.d
<= estack_ax_v
);
558 estack_pop(stack
, top
, ax
, bx
);
560 next_pc
+= sizeof(struct binary_op
);
564 OP(FILTER_OP_EQ_S64_DOUBLE
):
568 res
= (estack_bx_v
== estack_ax(stack
, top
)->u
.d
);
569 estack_pop(stack
, top
, ax
, bx
);
571 next_pc
+= sizeof(struct binary_op
);
574 OP(FILTER_OP_NE_S64_DOUBLE
):
578 res
= (estack_bx_v
!= estack_ax(stack
, top
)->u
.d
);
579 estack_pop(stack
, top
, ax
, bx
);
581 next_pc
+= sizeof(struct binary_op
);
584 OP(FILTER_OP_GT_S64_DOUBLE
):
588 res
= (estack_bx_v
> estack_ax(stack
, top
)->u
.d
);
589 estack_pop(stack
, top
, ax
, bx
);
591 next_pc
+= sizeof(struct binary_op
);
594 OP(FILTER_OP_LT_S64_DOUBLE
):
598 res
= (estack_bx_v
< estack_ax(stack
, top
)->u
.d
);
599 estack_pop(stack
, top
, ax
, bx
);
601 next_pc
+= sizeof(struct binary_op
);
604 OP(FILTER_OP_GE_S64_DOUBLE
):
608 res
= (estack_bx_v
>= estack_ax(stack
, top
)->u
.d
);
609 estack_pop(stack
, top
, ax
, bx
);
611 next_pc
+= sizeof(struct binary_op
);
614 OP(FILTER_OP_LE_S64_DOUBLE
):
618 res
= (estack_bx_v
<= estack_ax(stack
, top
)->u
.d
);
619 estack_pop(stack
, top
, ax
, bx
);
621 next_pc
+= sizeof(struct binary_op
);
626 OP(FILTER_OP_UNARY_PLUS
):
627 OP(FILTER_OP_UNARY_MINUS
):
628 OP(FILTER_OP_UNARY_NOT
):
629 ERR("unsupported non-specialized bytecode op %u\n",
630 (unsigned int) *(filter_opcode_t
*) pc
);
635 OP(FILTER_OP_UNARY_PLUS_S64
):
636 OP(FILTER_OP_UNARY_PLUS_DOUBLE
):
638 next_pc
+= sizeof(struct unary_op
);
641 OP(FILTER_OP_UNARY_MINUS_S64
):
643 estack_ax_v
= -estack_ax_v
;
644 next_pc
+= sizeof(struct unary_op
);
647 OP(FILTER_OP_UNARY_MINUS_DOUBLE
):
649 estack_ax(stack
, top
)->u
.d
= -estack_ax(stack
, top
)->u
.d
;
650 next_pc
+= sizeof(struct unary_op
);
653 OP(FILTER_OP_UNARY_NOT_S64
):
655 estack_ax_v
= !estack_ax_v
;
656 next_pc
+= sizeof(struct unary_op
);
659 OP(FILTER_OP_UNARY_NOT_DOUBLE
):
661 estack_ax(stack
, top
)->u
.d
= !estack_ax(stack
, top
)->u
.d
;
662 next_pc
+= sizeof(struct unary_op
);
669 struct logical_op
*insn
= (struct logical_op
*) pc
;
671 /* If AX is 0, skip and evaluate to 0 */
672 if (unlikely(estack_ax_v
== 0)) {
673 dbg_printf("Jumping to bytecode offset %u\n",
674 (unsigned int) insn
->skip_offset
);
675 next_pc
= start_pc
+ insn
->skip_offset
;
677 /* Pop 1 when jump not taken */
678 estack_pop(stack
, top
, ax
, bx
);
679 next_pc
+= sizeof(struct logical_op
);
685 struct logical_op
*insn
= (struct logical_op
*) pc
;
687 /* If AX is nonzero, skip and evaluate to 1 */
689 if (unlikely(estack_ax_v
!= 0)) {
691 dbg_printf("Jumping to bytecode offset %u\n",
692 (unsigned int) insn
->skip_offset
);
693 next_pc
= start_pc
+ insn
->skip_offset
;
695 /* Pop 1 when jump not taken */
696 estack_pop(stack
, top
, ax
, bx
);
697 next_pc
+= sizeof(struct logical_op
);
704 OP(FILTER_OP_LOAD_FIELD_REF_STRING
):
706 struct load_op
*insn
= (struct load_op
*) pc
;
707 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
709 dbg_printf("load field ref offset %u type string\n",
711 estack_push(stack
, top
, ax
, bx
);
712 estack_ax(stack
, top
)->u
.s
.str
=
713 *(const char * const *) &filter_stack_data
[ref
->offset
];
714 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
715 dbg_printf("Filter warning: loading a NULL string.\n");
719 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
720 estack_ax(stack
, top
)->u
.s
.literal
= 0;
721 dbg_printf("ref load string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
722 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
726 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE
):
728 struct load_op
*insn
= (struct load_op
*) pc
;
729 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
731 dbg_printf("load field ref offset %u type sequence\n",
733 estack_push(stack
, top
, ax
, bx
);
734 estack_ax(stack
, top
)->u
.s
.seq_len
=
735 *(unsigned long *) &filter_stack_data
[ref
->offset
];
736 estack_ax(stack
, top
)->u
.s
.str
=
737 *(const char **) (&filter_stack_data
[ref
->offset
738 + sizeof(unsigned long)]);
739 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
740 dbg_printf("Filter warning: loading a NULL sequence.\n");
744 estack_ax(stack
, top
)->u
.s
.literal
= 0;
745 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
749 OP(FILTER_OP_LOAD_FIELD_REF_S64
):
751 struct load_op
*insn
= (struct load_op
*) pc
;
752 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
754 dbg_printf("load field ref offset %u type s64\n",
756 estack_push(stack
, top
, ax
, bx
);
758 ((struct literal_numeric
*) &filter_stack_data
[ref
->offset
])->v
;
759 dbg_printf("ref load s64 %" PRIi64
"\n", estack_ax_v
);
760 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
764 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE
):
766 struct load_op
*insn
= (struct load_op
*) pc
;
767 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
769 dbg_printf("load field ref offset %u type double\n",
771 estack_push(stack
, top
, ax
, bx
);
772 memcpy(&estack_ax(stack
, top
)->u
.d
, &filter_stack_data
[ref
->offset
],
773 sizeof(struct literal_double
));
774 dbg_printf("ref load double %g\n", estack_ax(stack
, top
)->u
.d
);
775 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
779 OP(FILTER_OP_LOAD_STRING
):
781 struct load_op
*insn
= (struct load_op
*) pc
;
783 dbg_printf("load string %s\n", insn
->data
);
784 estack_push(stack
, top
, ax
, bx
);
785 estack_ax(stack
, top
)->u
.s
.str
= insn
->data
;
786 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
787 estack_ax(stack
, top
)->u
.s
.literal
= 1;
788 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
792 OP(FILTER_OP_LOAD_S64
):
794 struct load_op
*insn
= (struct load_op
*) pc
;
796 estack_push(stack
, top
, ax
, bx
);
797 estack_ax_v
= ((struct literal_numeric
*) insn
->data
)->v
;
798 dbg_printf("load s64 %" PRIi64
"\n", estack_ax_v
);
799 next_pc
+= sizeof(struct load_op
)
800 + sizeof(struct literal_numeric
);
804 OP(FILTER_OP_LOAD_DOUBLE
):
806 struct load_op
*insn
= (struct load_op
*) pc
;
808 estack_push(stack
, top
, ax
, bx
);
809 memcpy(&estack_ax(stack
, top
)->u
.d
, insn
->data
,
810 sizeof(struct literal_double
));
811 dbg_printf("load s64 %g\n", estack_ax(stack
, top
)->u
.d
);
812 next_pc
+= sizeof(struct load_op
)
813 + sizeof(struct literal_double
);
818 OP(FILTER_OP_CAST_TO_S64
):
819 ERR("unsupported non-specialized bytecode op %u\n",
820 (unsigned int) *(filter_opcode_t
*) pc
);
824 OP(FILTER_OP_CAST_DOUBLE_TO_S64
):
826 estack_ax_v
= (int64_t) estack_ax(stack
, top
)->u
.d
;
827 next_pc
+= sizeof(struct cast_op
);
831 OP(FILTER_OP_CAST_NOP
):
833 next_pc
+= sizeof(struct cast_op
);
839 /* return 0 (discard) on error */