Filter: double comparator produces s64
[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
52int reg_strcmp(struct reg reg[NR_REG], const char *cmp_type)
53{
54 const char *p = reg[REG_R0].str, *q = reg[REG_R1].str;
55 int ret;
56 int diff;
57
58 for (;;) {
59 int escaped_r0 = 0;
60
61 if (unlikely(p - reg[REG_R0].str > reg[REG_R0].seq_len || *p == '\0')) {
62 if (q - reg[REG_R1].str > reg[REG_R1].seq_len || *q == '\0')
63 diff = 0;
64 else
65 diff = -1;
66 break;
67 }
68 if (unlikely(q - reg[REG_R1].str > reg[REG_R1].seq_len || *q == '\0')) {
69 if (p - reg[REG_R0].str > reg[REG_R0].seq_len || *p == '\0')
70 diff = 0;
71 else
72 diff = 1;
73 break;
74 }
75 if (reg[REG_R0].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 (reg[REG_R1].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
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;
167 struct reg reg[NR_REG];
168#ifndef INTERPRETER_USE_SWITCH
169 static void *dispatch[NR_FILTER_OPS] = {
170 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
171
172 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
173
174 /* binary */
175 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
176 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
177 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
178 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
179 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
180 [ FILTER_OP_RSHIFT ] = &&LABEL_FILTER_OP_RSHIFT,
181 [ FILTER_OP_LSHIFT ] = &&LABEL_FILTER_OP_LSHIFT,
182 [ FILTER_OP_BIN_AND ] = &&LABEL_FILTER_OP_BIN_AND,
183 [ FILTER_OP_BIN_OR ] = &&LABEL_FILTER_OP_BIN_OR,
184 [ FILTER_OP_BIN_XOR ] = &&LABEL_FILTER_OP_BIN_XOR,
185
186 /* binary comparators */
187 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
188 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
189 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
190 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
191 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
192 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
193
194 /* string binary comparator */
195 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
196 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
197 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
198 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
199 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
200 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
201
202 /* s64 binary comparator */
203 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
204 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
205 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
206 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
207 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
208 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
209
210 /* double binary comparator */
211 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
212 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
213 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
214 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
215 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
216 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
217
218 /* unary */
219 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
220 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
221 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
222 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
223 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
224 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
225 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
226 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
227 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
228
229 /* logical */
230 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
231 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
232
233 /* load */
234 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
235 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
236 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
237 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
238 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
239
240 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
241 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
242 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
243
244 /* cast */
245 [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
246 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
247 [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
248 };
249#endif /* #ifndef INTERPRETER_USE_SWITCH */
250
251 START_OP
252
253 OP(FILTER_OP_UNKNOWN):
254 OP(FILTER_OP_LOAD_FIELD_REF):
255#ifdef INTERPRETER_USE_SWITCH
256 default:
257#endif /* INTERPRETER_USE_SWITCH */
258 ERR("unknown bytecode op %u\n",
259 (unsigned int) *(filter_opcode_t *) pc);
260 ret = -EINVAL;
261 goto end;
262
263 OP(FILTER_OP_RETURN):
264 retval = !!reg[0].v;
265 ret = 0;
266 goto end;
267
268 /* binary */
269 OP(FILTER_OP_MUL):
270 OP(FILTER_OP_DIV):
271 OP(FILTER_OP_MOD):
272 OP(FILTER_OP_PLUS):
273 OP(FILTER_OP_MINUS):
274 OP(FILTER_OP_RSHIFT):
275 OP(FILTER_OP_LSHIFT):
276 OP(FILTER_OP_BIN_AND):
277 OP(FILTER_OP_BIN_OR):
278 OP(FILTER_OP_BIN_XOR):
279 ERR("unsupported bytecode op %u\n",
280 (unsigned int) *(filter_opcode_t *) pc);
281 ret = -EINVAL;
282 goto end;
283
284 OP(FILTER_OP_EQ):
285 OP(FILTER_OP_NE):
286 OP(FILTER_OP_GT):
287 OP(FILTER_OP_LT):
288 OP(FILTER_OP_GE):
289 OP(FILTER_OP_LE):
290 ERR("unsupported non-specialized bytecode op %u\n",
291 (unsigned int) *(filter_opcode_t *) pc);
292 ret = -EINVAL;
293 goto end;
294
295 OP(FILTER_OP_EQ_STRING):
296 {
297 reg[REG_R0].v = (reg_strcmp(reg, "==") == 0);
298 reg[REG_R0].type = REG_S64;
299 next_pc += sizeof(struct binary_op);
300 PO;
301 }
302 OP(FILTER_OP_NE_STRING):
303 {
304 reg[REG_R0].v = (reg_strcmp(reg, "!=") != 0);
305 reg[REG_R0].type = REG_S64;
306 next_pc += sizeof(struct binary_op);
307 PO;
308 }
309 OP(FILTER_OP_GT_STRING):
310 {
311 reg[REG_R0].v = (reg_strcmp(reg, ">") > 0);
312 reg[REG_R0].type = REG_S64;
313 next_pc += sizeof(struct binary_op);
314 PO;
315 }
316 OP(FILTER_OP_LT_STRING):
317 {
318 reg[REG_R0].v = (reg_strcmp(reg, "<") < 0);
319 reg[REG_R0].type = REG_S64;
320 next_pc += sizeof(struct binary_op);
321 PO;
322 }
323 OP(FILTER_OP_GE_STRING):
324 {
325 reg[REG_R0].v = (reg_strcmp(reg, ">=") >= 0);
326 reg[REG_R0].type = REG_S64;
327 next_pc += sizeof(struct binary_op);
328 PO;
329 }
330 OP(FILTER_OP_LE_STRING):
331 {
332 reg[REG_R0].v = (reg_strcmp(reg, "<=") <= 0);
333 reg[REG_R0].type = REG_S64;
334 next_pc += sizeof(struct binary_op);
335 PO;
336 }
337
338 OP(FILTER_OP_EQ_S64):
339 {
340 reg[REG_R0].v = (reg[REG_R0].v == reg[REG_R1].v);
341 reg[REG_R0].type = REG_S64;
342 next_pc += sizeof(struct binary_op);
343 PO;
344 }
345 OP(FILTER_OP_NE_S64):
346 {
347 reg[REG_R0].v = (reg[REG_R0].v != reg[REG_R1].v);
348 reg[REG_R0].type = REG_S64;
349 next_pc += sizeof(struct binary_op);
350 PO;
351 }
352 OP(FILTER_OP_GT_S64):
353 {
354 reg[REG_R0].v = (reg[REG_R0].v > reg[REG_R1].v);
355 reg[REG_R0].type = REG_S64;
356 next_pc += sizeof(struct binary_op);
357 PO;
358 }
359 OP(FILTER_OP_LT_S64):
360 {
361 reg[REG_R0].v = (reg[REG_R0].v < reg[REG_R1].v);
362 reg[REG_R0].type = REG_S64;
363 next_pc += sizeof(struct binary_op);
364 PO;
365 }
366 OP(FILTER_OP_GE_S64):
367 {
368 reg[REG_R0].v = (reg[REG_R0].v >= reg[REG_R1].v);
369 reg[REG_R0].type = REG_S64;
370 next_pc += sizeof(struct binary_op);
371 PO;
372 }
373 OP(FILTER_OP_LE_S64):
374 {
375 reg[REG_R0].v = (reg[REG_R0].v <= reg[REG_R1].v);
376 reg[REG_R0].type = REG_S64;
377 next_pc += sizeof(struct binary_op);
378 PO;
379 }
380
381 OP(FILTER_OP_EQ_DOUBLE):
382 {
383 if (unlikely(reg[REG_R0].type == REG_S64))
384 reg[REG_R0].d = (double) reg[REG_R0].v;
385 else if (unlikely(reg[REG_R1].type == REG_S64))
386 reg[REG_R1].d = (double) reg[REG_R1].v;
387 reg[REG_R0].v = (reg[REG_R0].d == reg[REG_R1].d);
388 reg[REG_R0].type = REG_S64;
389 next_pc += sizeof(struct binary_op);
390 PO;
391 }
392 OP(FILTER_OP_NE_DOUBLE):
393 {
394 if (unlikely(reg[REG_R0].type == REG_S64))
395 reg[REG_R0].d = (double) reg[REG_R0].v;
396 else if (unlikely(reg[REG_R1].type == REG_S64))
397 reg[REG_R1].d = (double) reg[REG_R1].v;
398 reg[REG_R0].v = (reg[REG_R0].d != reg[REG_R1].d);
399 reg[REG_R0].type = REG_S64;
400 next_pc += sizeof(struct binary_op);
401 PO;
402 }
403 OP(FILTER_OP_GT_DOUBLE):
404 {
405 if (unlikely(reg[REG_R0].type == REG_S64))
406 reg[REG_R0].d = (double) reg[REG_R0].v;
407 else if (unlikely(reg[REG_R1].type == REG_S64))
408 reg[REG_R1].d = (double) reg[REG_R1].v;
409 reg[REG_R0].v = (reg[REG_R0].d > reg[REG_R1].d);
410 reg[REG_R0].type = REG_S64;
411 next_pc += sizeof(struct binary_op);
412 PO;
413 }
414 OP(FILTER_OP_LT_DOUBLE):
415 {
416 if (unlikely(reg[REG_R0].type == REG_S64))
417 reg[REG_R0].d = (double) reg[REG_R0].v;
418 else if (unlikely(reg[REG_R1].type == REG_S64))
419 reg[REG_R1].d = (double) reg[REG_R1].v;
420 reg[REG_R0].v = (reg[REG_R0].d < reg[REG_R1].d);
421 reg[REG_R0].type = REG_S64;
422 next_pc += sizeof(struct binary_op);
423 PO;
424 }
425 OP(FILTER_OP_GE_DOUBLE):
426 {
427 if (unlikely(reg[REG_R0].type == REG_S64))
428 reg[REG_R0].d = (double) reg[REG_R0].v;
429 else if (unlikely(reg[REG_R1].type == REG_S64))
430 reg[REG_R1].d = (double) reg[REG_R1].v;
431 reg[REG_R0].v = (reg[REG_R0].d >= reg[REG_R1].d);
432 reg[REG_R0].type = REG_S64;
433 next_pc += sizeof(struct binary_op);
434 PO;
435 }
436 OP(FILTER_OP_LE_DOUBLE):
437 {
438 if (unlikely(reg[REG_R0].type == REG_S64))
439 reg[REG_R0].d = (double) reg[REG_R0].v;
440 else if (unlikely(reg[REG_R1].type == REG_S64))
441 reg[REG_R1].d = (double) reg[REG_R1].v;
442 reg[REG_R0].v = (reg[REG_R0].d <= reg[REG_R1].d);
443 reg[REG_R0].type = REG_S64;
444 next_pc += sizeof(struct binary_op);
445 PO;
446 }
447
448 /* unary */
449 OP(FILTER_OP_UNARY_PLUS):
450 OP(FILTER_OP_UNARY_MINUS):
451 OP(FILTER_OP_UNARY_NOT):
452 ERR("unsupported non-specialized bytecode op %u\n",
453 (unsigned int) *(filter_opcode_t *) pc);
454 ret = -EINVAL;
455 goto end;
456
457
458 OP(FILTER_OP_UNARY_PLUS_S64):
459 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
460 {
461 next_pc += sizeof(struct unary_op);
462 PO;
463 }
464 OP(FILTER_OP_UNARY_MINUS_S64):
465 {
466 struct unary_op *insn = (struct unary_op *) pc;
467
468 reg[insn->reg].v = -reg[insn->reg].v;
469 next_pc += sizeof(struct unary_op);
470 PO;
471 }
472 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
473 {
474 struct unary_op *insn = (struct unary_op *) pc;
475
476 reg[insn->reg].d = -reg[insn->reg].d;
477 next_pc += sizeof(struct unary_op);
478 PO;
479 }
480 OP(FILTER_OP_UNARY_NOT_S64):
481 {
482 struct unary_op *insn = (struct unary_op *) pc;
483
484 reg[insn->reg].v = !reg[insn->reg].v;
485 next_pc += sizeof(struct unary_op);
486 PO;
487 }
488 OP(FILTER_OP_UNARY_NOT_DOUBLE):
489 {
490 struct unary_op *insn = (struct unary_op *) pc;
491
492 reg[insn->reg].d = !reg[insn->reg].d;
493 next_pc += sizeof(struct unary_op);
494 PO;
495 }
496
497 /* logical */
498 OP(FILTER_OP_AND):
499 {
500 struct logical_op *insn = (struct logical_op *) pc;
501
502 /* If REG_R0 is 0, skip and evaluate to 0 */
503 if (unlikely(reg[REG_R0].v == 0)) {
504 dbg_printf("Jumping to bytecode offset %u\n",
505 (unsigned int) insn->skip_offset);
506 next_pc = start_pc + insn->skip_offset;
507 } else {
508 next_pc += sizeof(struct logical_op);
509 }
510 PO;
511 }
512 OP(FILTER_OP_OR):
513 {
514 struct logical_op *insn = (struct logical_op *) pc;
515
516 /* If REG_R0 is nonzero, skip and evaluate to 1 */
517
518 if (unlikely(reg[REG_R0].v != 0)) {
519 reg[REG_R0].v = 1;
520 dbg_printf("Jumping to bytecode offset %u\n",
521 (unsigned int) insn->skip_offset);
522 next_pc = start_pc + insn->skip_offset;
523 } else {
524 next_pc += sizeof(struct logical_op);
525 }
526 PO;
527 }
528
529
530 /* load */
531 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
532 {
533 struct load_op *insn = (struct load_op *) pc;
534 struct field_ref *ref = (struct field_ref *) insn->data;
535
536 dbg_printf("load field ref offset %u type string\n",
537 ref->offset);
538 reg[insn->reg].str =
539 *(const char * const *) &filter_stack_data[ref->offset];
540 if (unlikely(!reg[insn->reg].str)) {
541 dbg_printf("Filter warning: loading a NULL string.\n");
542 ret = -EINVAL;
543 goto end;
544 }
545 reg[insn->reg].type = REG_STRING;
546 reg[insn->reg].seq_len = UINT_MAX;
547 reg[insn->reg].literal = 0;
548 dbg_printf("ref load string %s\n", reg[insn->reg].str);
549 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
550 PO;
551 }
552
553 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
554 {
555 struct load_op *insn = (struct load_op *) pc;
556 struct field_ref *ref = (struct field_ref *) insn->data;
557
558 dbg_printf("load field ref offset %u type sequence\n",
559 ref->offset);
560 reg[insn->reg].seq_len =
561 *(unsigned long *) &filter_stack_data[ref->offset];
562 reg[insn->reg].str =
563 *(const char **) (&filter_stack_data[ref->offset
564 + sizeof(unsigned long)]);
565 if (unlikely(!reg[insn->reg].str)) {
566 dbg_printf("Filter warning: loading a NULL sequence.\n");
567 ret = -EINVAL;
568 goto end;
569 }
570 reg[insn->reg].type = REG_STRING;
571 reg[insn->reg].literal = 0;
572 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
573 PO;
574 }
575
576 OP(FILTER_OP_LOAD_FIELD_REF_S64):
577 {
578 struct load_op *insn = (struct load_op *) pc;
579 struct field_ref *ref = (struct field_ref *) insn->data;
580
581 dbg_printf("load field ref offset %u type s64\n",
582 ref->offset);
583 memcpy(&reg[insn->reg].v, &filter_stack_data[ref->offset],
584 sizeof(struct literal_numeric));
585 reg[insn->reg].type = REG_S64;
586 dbg_printf("ref load s64 %" PRIi64 "\n", reg[insn->reg].v);
587 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
588 PO;
589 }
590
591 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
592 {
593 struct load_op *insn = (struct load_op *) pc;
594 struct field_ref *ref = (struct field_ref *) insn->data;
595
596 dbg_printf("load field ref offset %u type double\n",
597 ref->offset);
598 memcpy(&reg[insn->reg].d, &filter_stack_data[ref->offset],
599 sizeof(struct literal_double));
600 reg[insn->reg].type = REG_DOUBLE;
601 dbg_printf("ref load double %g\n", reg[insn->reg].d);
602 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
603 PO;
604 }
605
606 OP(FILTER_OP_LOAD_STRING):
607 {
608 struct load_op *insn = (struct load_op *) pc;
609
610 dbg_printf("load string %s\n", insn->data);
611 reg[insn->reg].str = insn->data;
612 reg[insn->reg].type = REG_STRING;
613 reg[insn->reg].seq_len = UINT_MAX;
614 reg[insn->reg].literal = 1;
615 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
616 PO;
617 }
618
619 OP(FILTER_OP_LOAD_S64):
620 {
621 struct load_op *insn = (struct load_op *) pc;
622
623 memcpy(&reg[insn->reg].v, insn->data,
624 sizeof(struct literal_numeric));
625 dbg_printf("load s64 %" PRIi64 "\n", reg[insn->reg].v);
626 reg[insn->reg].type = REG_S64;
627 next_pc += sizeof(struct load_op)
628 + sizeof(struct literal_numeric);
629 PO;
630 }
631
632 OP(FILTER_OP_LOAD_DOUBLE):
633 {
634 struct load_op *insn = (struct load_op *) pc;
635
636 memcpy(&reg[insn->reg].d, insn->data,
637 sizeof(struct literal_double));
638 dbg_printf("load s64 %g\n", reg[insn->reg].d);
639 reg[insn->reg].type = REG_DOUBLE;
640 next_pc += sizeof(struct load_op)
641 + sizeof(struct literal_double);
642 PO;
643 }
644
645 /* cast */
646 OP(FILTER_OP_CAST_TO_S64):
647 ERR("unsupported non-specialized bytecode op %u\n",
648 (unsigned int) *(filter_opcode_t *) pc);
649 ret = -EINVAL;
650 goto end;
651
652 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
653 {
654 struct cast_op *insn = (struct cast_op *) pc;
655
656 reg[insn->reg].v = (int64_t) reg[insn->reg].d;
657 reg[insn->reg].type = REG_S64;
658 next_pc += sizeof(struct cast_op);
659 PO;
660 }
661
662 OP(FILTER_OP_CAST_NOP):
663 {
664 next_pc += sizeof(struct cast_op);
665 PO;
666 }
667
668 END_OP
669end:
670 /* return 0 (discard) on error */
671 if (ret)
672 return 0;
673 return retval;
674}
675
676#undef START_OP
677#undef OP
678#undef PO
679#undef END_OP
This page took 0.049147 seconds and 4 git commands to generate.