void npfctl_bpf_endgroup(npf_bpf_t *ctx) { struct bpf_program *bp = &ctx->prog; const size_t curoff = bp->bf_len; /* If there are no blocks or only one - nothing to do. */ if ((ctx->nblocks - ctx->gblock) <= 1) { ctx->goff = ctx->gblock = 0; return; } /* * Append a failure return as a fall-through i.e. if there is * no match within the group. */ struct bpf_insn insns_ret[] = { BPF_STMT(BPF_RET+BPF_K, NPF_BPF_FAILURE), }; add_insns(ctx, insns_ret, __arraycount(insns_ret)); /* * Adjust jump offsets: on match - jump outside the group i.e. * to the current offset. Otherwise, jump to the next instruction * which would lead to the fall-through code above if none matches. */ fixup_jumps(ctx, ctx->goff, curoff, true); ctx->goff = ctx->gblock = 0; }
void unroll_this(pTHX_ OP* op) { struct sljit_compiler* compiler = sljit_create_compiler(); HV* seenops = newHV(); #ifdef DEBUG if (getenv("RUNOPS_OPTIMIZED_DEBUG")) { CV *runcv = Perl_find_runcv(NULL); sljit_compiler_verbose(compiler, stderr); DEBUGf(("Unroll %s::%s cv=%p, op=%p (%s)\n", HvNAME_get(CvSTASH(runcv)), GvENAME(CvGV(runcv)), runcv, op, sljit_get_platform_name())); } #endif sljit_emit_enter(compiler, 0, 2, 1, 0); unroll_tree(compiler, seenops, op, NULL); fixup_jumps(compiler, needjumps, labels); // This is needed for things that drop off the runloop without a // return, e.g. S_sortcv. TODO: Make conditional? sljit_emit_return(compiler, SLJIT_MEM, (sljit_w) &PL_op); op->op_ppaddr = sljit_generate_code(compiler); op->op_spare = 3; DEBUGf(("Code at %p\n", op->op_ppaddr)); labels = NULL; needjumps = NULL; SvREFCNT_dec(seenops); sljit_free_compiler(compiler); }
struct bpf_program * npfctl_bpf_complete(npf_bpf_t *ctx) { struct bpf_program *bp = &ctx->prog; const u_int retoff = bp->bf_len; /* Add the return fragment (success and failure paths). */ struct bpf_insn insns_ret[] = { BPF_STMT(BPF_RET+BPF_K, NPF_BPF_SUCCESS), BPF_STMT(BPF_RET+BPF_K, NPF_BPF_FAILURE), }; add_insns(ctx, insns_ret, __arraycount(insns_ret)); /* Fixup all jumps to the main failure path. */ fixup_jumps(ctx, 0, retoff, false); return &ctx->prog; }