]> git.ipfire.org Git - thirdparty/vectorscan.git/commitdiff
SHENG64: 64-state 1-byte shuffle based DFA.
authorChang, Harry <harry.chang@intel.com>
Fri, 10 Jul 2020 13:26:17 +0000 (13:26 +0000)
committerKonstantinos Margaritis <markos@users.noreply.github.com>
Mon, 25 Jan 2021 12:13:13 +0000 (14:13 +0200)
16 files changed:
src/nfa/nfa_api_dispatch.c
src/nfa/nfa_build_util.cpp
src/nfa/nfa_dump_dispatch.cpp
src/nfa/nfa_internal.h
src/nfa/sheng.c
src/nfa/sheng.h
src/nfa/sheng_defs.h
src/nfa/sheng_impl.h
src/nfa/sheng_impl4.h
src/nfa/sheng_internal.h
src/nfa/shengcompile.cpp
src/nfa/shengcompile.h
src/nfa/shengdump.cpp
src/nfa/shengdump.h
src/rose/rose_build_bytecode.cpp
src/smallwrite/smallwrite_build.cpp

index 6786cbafb872a4b4e6034ae1cf67d1a8efea9e63..4b45cf0638ab2df5ad170eca36e7b80bb0059775 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, Intel Corporation
+ * Copyright (c) 2015-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -77,6 +77,7 @@
         DISPATCH_CASE(MCSHENG_NFA_8, McSheng8, dbnt_func);                     \
         DISPATCH_CASE(MCSHENG_NFA_16, McSheng16, dbnt_func);                   \
         DISPATCH_CASE(SHENG_NFA_32, Sheng32, dbnt_func);                       \
+        DISPATCH_CASE(SHENG_NFA_64, Sheng64, dbnt_func);                       \
     default:                                                                   \
         assert(0);                                                             \
     }
index 0ce6512e9ee8db93c824788be406dcb39ef53857..df789d7df29e0122c29ed3f48d78810f89f9e6a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, Intel Corporation
+ * Copyright (c) 2015-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -462,6 +462,22 @@ const nfa_dispatch_fn NFATraits<SHENG_NFA_32>::has_repeats_other_than_firsts = d
 const char *NFATraits<SHENG_NFA_32>::name = "Sheng 32";
 #endif
 
+template<> struct NFATraits<SHENG_NFA_64> {
+    UNUSED static const char *name;
+    static const NFACategory category = NFA_OTHER;
+    static const u32 stateAlign = 1;
+    static const bool fast = true;
+    static const nfa_dispatch_fn has_accel;
+    static const nfa_dispatch_fn has_repeats;
+    static const nfa_dispatch_fn has_repeats_other_than_firsts;
+};
+const nfa_dispatch_fn NFATraits<SHENG_NFA_64>::has_accel = has_accel_sheng;
+const nfa_dispatch_fn NFATraits<SHENG_NFA_64>::has_repeats = dispatch_false;
+const nfa_dispatch_fn NFATraits<SHENG_NFA_64>::has_repeats_other_than_firsts = dispatch_false;
+#if defined(DUMP_SUPPORT)
+const char *NFATraits<SHENG_NFA_64>::name = "Sheng 64";
+#endif
+
 } // namespace
 
 #if defined(DUMP_SUPPORT)
index 07dc53476f8544b54a06f0b6c5532cab452a2281..09137ccdcba7efc1f6089cd13c76a11d08117b29 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, Intel Corporation
+ * Copyright (c) 2015-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -82,6 +82,7 @@ namespace ue2 {
         DISPATCH_CASE(MCSHENG_NFA_8, McSheng8, dbnt_func);                     \
         DISPATCH_CASE(MCSHENG_NFA_16, McSheng16, dbnt_func);                   \
         DISPATCH_CASE(SHENG_NFA_32, Sheng32, dbnt_func);                       \
+        DISPATCH_CASE(SHENG_NFA_64, Sheng64, dbnt_func);                       \
     default:                                                                   \
         assert(0);                                                             \
     }
index 0ec0b9d7eb2cce9480564e3de8fe5584d2e783e3..de43c0b539629613929919be435c44d73443693e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, Intel Corporation
+ * Copyright (c) 2015-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -73,6 +73,7 @@ enum NFAEngineType {
     MCSHENG_NFA_8,      /**< magic pseudo nfa */
     MCSHENG_NFA_16,     /**< magic pseudo nfa */
     SHENG_NFA_32,       /**< magic pseudo nfa */
+    SHENG_NFA_64,       /**< magic pseudo nfa */
     /** \brief bogus NFA - not used */
     INVALID_NFA
 };
@@ -167,12 +168,17 @@ static really_inline int isSheng16Type(u8 t) {
 static really_inline int isSheng32Type(u8 t) {
     return t == SHENG_NFA_32;
 }
+
+/** \brief True if the given type (from NFA::type) is a Sheng64 DFA. */
+static really_inline int isSheng64Type(u8 t) {
+    return t == SHENG_NFA_64;
+}
 #endif
 
-/** \brief True if the given type (from NFA::type) is a Sheng/Sheng32 DFA. */
+/** \brief True if the given type (from NFA::type) is a Sheng16/32/64 DFA. */
 static really_inline int isShengType(u8 t) {
 #if defined(HAVE_AVX512VBMI)
-    return t == SHENG_NFA || t == SHENG_NFA_32;
+    return t == SHENG_NFA || t == SHENG_NFA_32 || t == SHENG_NFA_64;
 #else
     return t == SHENG_NFA;
 #endif
index 7d30220691479ac4fd3365ca38e52d7663854e46..3f36e21891710819a0f81aa9c66cbb86513b87f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, Intel Corporation
+ * Copyright (c) 2016-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -155,6 +155,7 @@ char fireReports(const struct sheng *sh, NfaCallback cb, void *ctxt,
 }
 
 #if defined(HAVE_AVX512VBMI)
+// Sheng32
 static really_inline
 const struct sheng32 *get_sheng32(const struct NFA *n) {
     return (const struct sheng32 *)getImplNfa(n);
@@ -256,6 +257,100 @@ char fireReports32(const struct sheng32 *sh, NfaCallback cb, void *ctxt,
     }
     return MO_CONTINUE_MATCHING; /* continue execution */
 }
+
+// Sheng64
+static really_inline
+const struct sheng64 *get_sheng64(const struct NFA *n) {
+    return (const struct sheng64 *)getImplNfa(n);
+}
+
+static really_inline
+const struct sstate_aux *get_aux64(const struct sheng64 *sh, u8 id) {
+    u32 offset = sh->aux_offset - sizeof(struct NFA) +
+            (id & SHENG64_STATE_MASK) * sizeof(struct sstate_aux);
+    DEBUG_PRINTF("Getting aux for state %u at offset %llu\n",
+                 id & SHENG64_STATE_MASK, (u64a)offset + sizeof(struct NFA));
+    return (const struct sstate_aux *)((const char *) sh + offset);
+}
+
+static really_inline
+const struct report_list *get_rl64(const struct sheng64 *sh,
+                                   const struct sstate_aux *aux) {
+    DEBUG_PRINTF("Getting report list at offset %u\n", aux->accept);
+    return (const struct report_list *)
+        ((const char *)sh + aux->accept - sizeof(struct NFA));
+}
+
+static really_inline
+const struct report_list *get_eod_rl64(const struct sheng64 *sh,
+                                       const struct sstate_aux *aux) {
+    DEBUG_PRINTF("Getting EOD report list at offset %u\n", aux->accept);
+    return (const struct report_list *)
+        ((const char *)sh + aux->accept_eod - sizeof(struct NFA));
+}
+
+static really_inline
+char sheng64HasAccept(const struct sheng64 *sh, const struct sstate_aux *aux,
+                      ReportID report) {
+    assert(sh && aux);
+
+    const struct report_list *rl = get_rl64(sh, aux);
+    assert(ISALIGNED_N(rl, 4));
+
+    DEBUG_PRINTF("report list has %u entries\n", rl->count);
+
+    for (u32 i = 0; i < rl->count; i++) {
+        if (rl->report[i] == report) {
+            DEBUG_PRINTF("reporting %u\n", rl->report[i]);
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+static really_inline
+char fireReports64(const struct sheng64 *sh, NfaCallback cb, void *ctxt,
+                   const u8 state, u64a loc, u8 *const cached_accept_state,
+                   ReportID *const cached_accept_id, char eod) {
+    DEBUG_PRINTF("reporting matches @ %llu\n", loc);
+
+    if (!eod && state == *cached_accept_state) {
+        DEBUG_PRINTF("reporting %u\n", *cached_accept_id);
+        if (cb(0, loc, *cached_accept_id, ctxt) == MO_HALT_MATCHING) {
+            return MO_HALT_MATCHING; /* termination requested */
+        }
+
+        return MO_CONTINUE_MATCHING; /* continue execution */
+    }
+    const struct sstate_aux *aux = get_aux64(sh, state);
+    const struct report_list *rl = eod ? get_eod_rl64(sh, aux) :
+                                         get_rl64(sh, aux);
+    assert(ISALIGNED(rl));
+
+    DEBUG_PRINTF("report list has %u entries\n", rl->count);
+    u32 count = rl->count;
+
+    if (!eod && count == 1) {
+        *cached_accept_state = state;
+        *cached_accept_id = rl->report[0];
+
+        DEBUG_PRINTF("reporting %u\n", rl->report[0]);
+        if (cb(0, loc, rl->report[0], ctxt) == MO_HALT_MATCHING) {
+            return MO_HALT_MATCHING; /* termination requested */
+        }
+
+        return MO_CONTINUE_MATCHING; /* continue execution */
+    }
+
+    for (u32 i = 0; i < count; i++) {
+        DEBUG_PRINTF("reporting %u\n", rl->report[i]);
+        if (cb(0, loc, rl->report[i], ctxt) == MO_HALT_MATCHING) {
+            return MO_HALT_MATCHING; /* termination requested */
+        }
+    }
+    return MO_CONTINUE_MATCHING; /* continue execution */
+}
 #endif // end of HAVE_AVX512VBMI
 
 /* include Sheng function definitions */
@@ -777,6 +872,7 @@ char nfaExecSheng_expandState(UNUSED const struct NFA *nfa, void *dest,
 }
 
 #if defined(HAVE_AVX512VBMI)
+// Sheng32
 static really_inline
 char runSheng32Cb(const struct sheng32 *sh, NfaCallback cb, void *ctxt,
                   u64a offset, u8 *const cached_accept_state,
@@ -1294,4 +1390,488 @@ char nfaExecSheng32_expandState(UNUSED const struct NFA *nfa, void *dest,
     *(u8 *)dest = *(const u8 *)src;
     return 0;
 }
+
+// Sheng64
+static really_inline
+char runSheng64Cb(const struct sheng64 *sh, NfaCallback cb, void *ctxt,
+                  u64a offset, u8 *const cached_accept_state,
+                  ReportID *const cached_accept_id, const u8 *cur_buf,
+                  const u8 *start, const u8 *end, u8 can_die,
+                  u8 single, const u8 **scanned, u8 *state) {
+    DEBUG_PRINTF("Scanning %llu bytes (offset %llu) in callback mode\n",
+                 (u64a)(end - start), offset);
+    DEBUG_PRINTF("start: %lli end: %lli\n", (s64a)(start - cur_buf),
+                 (s64a)(end - cur_buf));
+    DEBUG_PRINTF("can die: %u single: %u\n", !!can_die, !!single);
+    int rv;
+    /* scan and report all matches */
+    if (can_die) {
+        rv = sheng64_4_cod(state, cb, ctxt, sh, cached_accept_state,
+                           cached_accept_id, single, offset, cur_buf,
+                           start, end, scanned);
+        if (rv == MO_HALT_MATCHING) {
+            return MO_DEAD;
+        }
+        rv = sheng64_cod(state, cb, ctxt, sh, cached_accept_state,
+                         cached_accept_id, single, offset, cur_buf,
+                         *scanned, end, scanned);
+    } else {
+        rv = sheng64_4_co(state, cb, ctxt, sh, cached_accept_state,
+                          cached_accept_id, single, offset, cur_buf,
+                          start, end, scanned);
+        if (rv == MO_HALT_MATCHING) {
+            return MO_DEAD;
+        }
+        rv = sheng64_co(state, cb, ctxt, sh, cached_accept_state,
+                        cached_accept_id, single, offset, cur_buf,
+                        *scanned, end, scanned);
+    }
+    if (rv == MO_HALT_MATCHING) {
+        return MO_DEAD;
+    }
+    return MO_ALIVE;
+}
+
+static really_inline
+void runSheng64Nm(const struct sheng64 *sh, NfaCallback cb, void *ctxt,
+                  u64a offset, u8 *const cached_accept_state,
+                  ReportID *const cached_accept_id, const u8 *cur_buf,
+                  const u8 *start, const u8 *end, u8 can_die,
+                  u8 single, const u8 **scanned, u8 *state) {
+    DEBUG_PRINTF("Scanning %llu bytes (offset %llu) in nomatch mode\n",
+                 (u64a)(end - start), offset);
+    DEBUG_PRINTF("start: %lli end: %lli\n", (s64a)(start - cur_buf),
+                 (s64a)(end - cur_buf));
+    DEBUG_PRINTF("can die: %u single: %u\n", !!can_die, !!single);
+    /* just scan the buffer */
+    if (can_die) {
+        sheng64_4_nmd(state, cb, ctxt, sh, cached_accept_state,
+                      cached_accept_id, single, offset, cur_buf,
+                      start, end, scanned);
+        sheng64_nmd(state, cb, ctxt, sh, cached_accept_state, cached_accept_id,
+                    single, offset, cur_buf, *scanned, end, scanned);
+    } else {
+        sheng64_4_nm(state, cb, ctxt, sh, cached_accept_state, cached_accept_id,
+                     single, offset, cur_buf, start, end, scanned);
+        sheng64_nm(state, cb, ctxt, sh, cached_accept_state, cached_accept_id,
+                   single, offset, cur_buf, *scanned, end, scanned);
+    }
+}
+
+static really_inline
+char runSheng64Sam(const struct sheng64 *sh, NfaCallback cb, void *ctxt,
+                   u64a offset, u8 *const cached_accept_state,
+                   ReportID *const cached_accept_id, const u8 *cur_buf,
+                   const u8 *start, const u8 *end, u8 can_die,
+                   u8 single, const u8 **scanned, u8 *state) {
+    DEBUG_PRINTF("Scanning %llu bytes (offset %llu) in stop at match mode\n",
+                 (u64a)(end - start), offset);
+    DEBUG_PRINTF("start: %lli end: %lli\n", (s64a)(start - cur_buf),
+                 (s64a)(end - cur_buf));
+    DEBUG_PRINTF("can die: %u single: %u\n", !!can_die, !!single);
+    int rv;
+    /* scan until first match */
+    if (can_die) {
+        rv = sheng64_4_samd(state, cb, ctxt, sh, cached_accept_state,
+                            cached_accept_id, single, offset, cur_buf,
+                            start, end, scanned);
+        if (rv == MO_HALT_MATCHING) {
+            return MO_DEAD;
+        }
+        /* if we stopped before we expected, we found a match */
+        if (rv == MO_MATCHES_PENDING) {
+            return MO_MATCHES_PENDING;
+        }
+
+        rv = sheng64_samd(state, cb, ctxt, sh, cached_accept_state,
+                          cached_accept_id, single, offset, cur_buf,
+                          *scanned, end, scanned);
+    } else {
+        rv = sheng64_4_sam(state, cb, ctxt, sh, cached_accept_state,
+                           cached_accept_id, single, offset, cur_buf,
+                           start, end, scanned);
+        if (rv == MO_HALT_MATCHING) {
+            return MO_DEAD;
+        }
+        /* if we stopped before we expected, we found a match */
+        if (rv == MO_MATCHES_PENDING) {
+            return MO_MATCHES_PENDING;
+        }
+
+        rv = sheng64_sam(state, cb, ctxt, sh, cached_accept_state,
+                         cached_accept_id, single, offset, cur_buf,
+                         *scanned, end, scanned);
+    }
+    if (rv == MO_HALT_MATCHING) {
+        return MO_DEAD;
+    }
+    /* if we stopped before we expected, we found a match */
+    if (rv == MO_MATCHES_PENDING) {
+        return MO_MATCHES_PENDING;
+    }
+    return MO_ALIVE;
+}
+
+static never_inline
+char runSheng64(const struct sheng64 *sh, struct mq *q, s64a b_end,
+                enum MatchMode mode) {
+    u8 state = *(u8 *)q->state;
+    u8 can_die = sh->flags & SHENG_FLAG_CAN_DIE;
+    u8 single = sh->flags & SHENG_FLAG_SINGLE_REPORT;
+
+    u8 cached_accept_state = 0;
+    ReportID cached_accept_id = 0;
+
+    DEBUG_PRINTF("starting Sheng64 execution in state %u\n",
+                 state & SHENG64_STATE_MASK);
+
+    if (q->report_current) {
+        DEBUG_PRINTF("reporting current pending matches\n");
+        assert(sh);
+
+        q->report_current = 0;
+
+        int rv;
+        if (single) {
+            rv = fireSingleReport(q->cb, q->context, sh->report,
+                                  q_cur_offset(q));
+        } else {
+            rv = fireReports64(sh, q->cb, q->context, state, q_cur_offset(q),
+                               &cached_accept_state, &cached_accept_id, 0);
+        }
+        if (rv == MO_HALT_MATCHING) {
+            DEBUG_PRINTF("exiting in state %u\n", state & SHENG64_STATE_MASK);
+            return MO_DEAD;
+        }
+
+        DEBUG_PRINTF("proceeding with matching\n");
+    }
+
+    assert(q_cur_type(q) == MQE_START);
+    s64a start = q_cur_loc(q);
+
+    DEBUG_PRINTF("offset: %lli, location: %lli, mode: %s\n", q->offset, start,
+                 mode == CALLBACK_OUTPUT ? "CALLBACK OUTPUT" :
+                     mode == NO_MATCHES ? "NO MATCHES" :
+                         mode == STOP_AT_MATCH ? "STOP AT MATCH" : "???");
+
+    DEBUG_PRINTF("processing event @ %lli: %s\n", q->offset + q_cur_loc(q),
+                 q_cur_type(q) == MQE_START ? "START" :
+                     q_cur_type(q) == MQE_TOP ? "TOP" :
+                         q_cur_type(q) == MQE_END ? "END" : "???");
+
+    const u8* cur_buf;
+    if (start < 0) {
+        DEBUG_PRINTF("negative location, scanning history\n");
+        DEBUG_PRINTF("min location: %zd\n", -q->hlength);
+        cur_buf = q->history + q->hlength;
+    } else {
+        DEBUG_PRINTF("positive location, scanning buffer\n");
+        DEBUG_PRINTF("max location: %lli\n", b_end);
+        cur_buf = q->buffer;
+    }
+
+    /* if we our queue event is past our end */
+    if (mode != NO_MATCHES && q_cur_loc(q) > b_end) {
+        DEBUG_PRINTF("current location past buffer end\n");
+        DEBUG_PRINTF("setting q location to %llu\n", b_end);
+        DEBUG_PRINTF("exiting in state %u\n", state & SHENG64_STATE_MASK);
+        q->items[q->cur].location = b_end;
+        return MO_ALIVE;
+    }
+
+    q->cur++;
+
+    s64a cur_start = start;
+
+    while (1) {
+        DEBUG_PRINTF("processing event @ %lli: %s\n", q->offset + q_cur_loc(q),
+                     q_cur_type(q) == MQE_START ? "START" :
+                             q_cur_type(q) == MQE_TOP ? "TOP" :
+                                     q_cur_type(q) == MQE_END ? "END" : "???");
+        s64a end = q_cur_loc(q);
+        if (mode != NO_MATCHES) {
+            end = MIN(end, b_end);
+        }
+        assert(end <= (s64a) q->length);
+        s64a cur_end = end;
+
+        /* we may cross the border between history and current buffer */
+        if (cur_start < 0) {
+            cur_end = MIN(0, cur_end);
+        }
+
+        DEBUG_PRINTF("start: %lli end: %lli\n", start, end);
+
+        /* don't scan zero length buffer */
+        if (cur_start != cur_end) {
+            const u8 * scanned = cur_buf;
+            char rv;
+
+            if (mode == NO_MATCHES) {
+                runSheng64Nm(sh, q->cb, q->context, q->offset,
+                             &cached_accept_state, &cached_accept_id, cur_buf,
+                             cur_buf + cur_start, cur_buf + cur_end, can_die,
+                             single, &scanned, &state);
+            } else if (mode == CALLBACK_OUTPUT) {
+                rv = runSheng64Cb(sh, q->cb, q->context, q->offset,
+                                  &cached_accept_state, &cached_accept_id,
+                                  cur_buf, cur_buf + cur_start, cur_buf + cur_end,
+                                  can_die, single, &scanned, &state);
+                if (rv == MO_DEAD) {
+                    DEBUG_PRINTF("exiting in state %u\n",
+                                 state & SHENG64_STATE_MASK);
+                    return MO_DEAD;
+                }
+            } else if (mode == STOP_AT_MATCH) {
+                rv = runSheng64Sam(sh, q->cb, q->context, q->offset,
+                                   &cached_accept_state, &cached_accept_id,
+                                   cur_buf, cur_buf + cur_start,
+                                   cur_buf + cur_end, can_die, single,
+                                   &scanned, &state);
+                if (rv == MO_DEAD) {
+                    DEBUG_PRINTF("exiting in state %u\n",
+                                 state & SHENG64_STATE_MASK);
+                    return rv;
+                } else if (rv == MO_MATCHES_PENDING) {
+                    assert(q->cur);
+                    DEBUG_PRINTF("found a match, setting q location to %zd\n",
+                                 scanned - cur_buf + 1);
+                    q->cur--;
+                    q->items[q->cur].type = MQE_START;
+                    q->items[q->cur].location =
+                            scanned - cur_buf + 1; /* due to exiting early */
+                    *(u8 *)q->state = state;
+                    DEBUG_PRINTF("exiting in state %u\n",
+                                 state & SHENG64_STATE_MASK);
+                    return rv;
+                }
+            } else {
+                assert(!"invalid scanning mode!");
+            }
+            assert(scanned == cur_buf + cur_end);
+
+            cur_start = cur_end;
+        }
+
+        /* if we our queue event is past our end */
+        if (mode != NO_MATCHES && q_cur_loc(q) > b_end) {
+            DEBUG_PRINTF("current location past buffer end\n");
+            DEBUG_PRINTF("setting q location to %llu\n", b_end);
+            DEBUG_PRINTF("exiting in state %u\n", state & SHENG64_STATE_MASK);
+            q->cur--;
+            q->items[q->cur].type = MQE_START;
+            q->items[q->cur].location = b_end;
+            *(u8 *)q->state = state;
+            return MO_ALIVE;
+        }
+
+        /* crossing over into actual buffer */
+        if (cur_start == 0) {
+            DEBUG_PRINTF("positive location, scanning buffer\n");
+            DEBUG_PRINTF("max offset: %lli\n", b_end);
+            cur_buf = q->buffer;
+        }
+
+        /* continue scanning the same buffer */
+        if (end != cur_end) {
+            continue;
+        }
+
+        switch (q_cur_type(q)) {
+        case MQE_END:
+            *(u8 *)q->state = state;
+            q->cur++;
+            DEBUG_PRINTF("exiting in state %u\n", state & SHENG64_STATE_MASK);
+            if (can_die) {
+                return (state & SHENG64_STATE_DEAD) ? MO_DEAD : MO_ALIVE;
+            }
+            return MO_ALIVE;
+        case MQE_TOP:
+            if (q->offset + cur_start == 0) {
+                DEBUG_PRINTF("Anchored start, going to state %u\n",
+                             sh->anchored);
+                state = sh->anchored;
+            } else {
+                u8 new_state = get_aux64(sh, state)->top;
+                DEBUG_PRINTF("Top event %u->%u\n", state & SHENG64_STATE_MASK,
+                             new_state & SHENG64_STATE_MASK);
+                state = new_state;
+            }
+            break;
+        default:
+            assert(!"invalid queue event");
+            break;
+        }
+        q->cur++;
+    }
+}
+
+char nfaExecSheng64_B(const struct NFA *n, u64a offset, const u8 *buffer,
+                      size_t length, NfaCallback cb, void *context) {
+    DEBUG_PRINTF("smallwrite Sheng64\n");
+    assert(n->type == SHENG_NFA_64);
+    const struct sheng64 *sh = getImplNfa(n);
+    u8 state = sh->anchored;
+    u8 can_die = sh->flags & SHENG_FLAG_CAN_DIE;
+    u8 single = sh->flags & SHENG_FLAG_SINGLE_REPORT;
+    u8 cached_accept_state = 0;
+    ReportID cached_accept_id = 0;
+
+    /* scan and report all matches */
+    int rv;
+    s64a end = length;
+    const u8 *scanned;
+
+    rv = runSheng64Cb(sh, cb, context, offset, &cached_accept_state,
+                      &cached_accept_id, buffer, buffer, buffer + end, can_die,
+                      single, &scanned, &state);
+    if (rv == MO_DEAD) {
+        DEBUG_PRINTF("exiting in state %u\n",
+                     state & SHENG64_STATE_MASK);
+        return MO_DEAD;
+    }
+
+    DEBUG_PRINTF("%u\n", state & SHENG64_STATE_MASK);
+
+    const struct sstate_aux *aux = get_aux64(sh, state);
+
+    if (aux->accept_eod) {
+        DEBUG_PRINTF("Reporting EOD matches\n");
+        fireReports64(sh, cb, context, state, end + offset,
+                      &cached_accept_state, &cached_accept_id, 1);
+    }
+
+    return state & SHENG64_STATE_DEAD ? MO_DEAD : MO_ALIVE;
+}
+
+char nfaExecSheng64_Q(const struct NFA *n, struct mq *q, s64a end) {
+    const struct sheng64 *sh = get_sheng64(n);
+    char rv = runSheng64(sh, q, end, CALLBACK_OUTPUT);
+    return rv;
+}
+
+char nfaExecSheng64_Q2(const struct NFA *n, struct mq *q, s64a end) {
+    const struct sheng64 *sh = get_sheng64(n);
+    char rv = runSheng64(sh, q, end, STOP_AT_MATCH);
+    return rv;
+}
+
+char nfaExecSheng64_QR(const struct NFA *n, struct mq *q, ReportID report) {
+    assert(q_cur_type(q) == MQE_START);
+
+    const struct sheng64 *sh = get_sheng64(n);
+    char rv = runSheng64(sh, q, 0 /* end */, NO_MATCHES);
+
+    if (rv && nfaExecSheng64_inAccept(n, report, q)) {
+        return MO_MATCHES_PENDING;
+    }
+    return rv;
+}
+
+char nfaExecSheng64_inAccept(const struct NFA *n, ReportID report,
+                             struct mq *q) {
+    assert(n && q);
+
+    const struct sheng64 *sh = get_sheng64(n);
+    u8 s = *(const u8 *)q->state;
+    DEBUG_PRINTF("checking accepts for %u\n", (u8)(s & SHENG64_STATE_MASK));
+
+    const struct sstate_aux *aux = get_aux64(sh, s);
+
+    if (!aux->accept) {
+        return 0;
+    }
+
+    return sheng64HasAccept(sh, aux, report);
+}
+
+char nfaExecSheng64_inAnyAccept(const struct NFA *n, struct mq *q) {
+    assert(n && q);
+
+    const struct sheng64 *sh = get_sheng64(n);
+    u8 s = *(const u8 *)q->state;
+    DEBUG_PRINTF("checking accepts for %u\n", (u8)(s & SHENG64_STATE_MASK));
+
+    const struct sstate_aux *aux = get_aux64(sh, s);
+    return !!aux->accept;
+}
+
+char nfaExecSheng64_testEOD(const struct NFA *nfa, const char *state,
+                            UNUSED const char *streamState, u64a offset,
+                            NfaCallback cb, void *ctxt) {
+    assert(nfa);
+
+    const struct sheng64 *sh = get_sheng64(nfa);
+    u8 s = *(const u8 *)state;
+    DEBUG_PRINTF("checking EOD accepts for %u\n", (u8)(s & SHENG64_STATE_MASK));
+
+    const struct sstate_aux *aux = get_aux64(sh, s);
+
+    if (!aux->accept_eod) {
+        return MO_CONTINUE_MATCHING;
+    }
+
+    return fireReports64(sh, cb, ctxt, s, offset, NULL, NULL, 1);
+}
+
+char nfaExecSheng64_reportCurrent(const struct NFA *n, struct mq *q) {
+    const struct sheng64 *sh = (const struct sheng64 *)getImplNfa(n);
+    NfaCallback cb = q->cb;
+    void *ctxt = q->context;
+    u8 s = *(u8 *)q->state;
+    const struct sstate_aux *aux = get_aux64(sh, s);
+    u64a offset = q_cur_offset(q);
+    u8 cached_state_id = 0;
+    ReportID cached_report_id = 0;
+    assert(q_cur_type(q) == MQE_START);
+
+    if (aux->accept) {
+        if (sh->flags & SHENG_FLAG_SINGLE_REPORT) {
+            fireSingleReport(cb, ctxt, sh->report, offset);
+        } else {
+            fireReports64(sh, cb, ctxt, s, offset, &cached_state_id,
+                          &cached_report_id, 0);
+        }
+    }
+
+    return 0;
+}
+
+char nfaExecSheng64_initCompressedState(const struct NFA *nfa, u64a offset,
+                                        void *state, UNUSED u8 key) {
+    const struct sheng64 *sh = get_sheng64(nfa);
+    u8 *s = (u8 *)state;
+    *s = offset ? sh->floating: sh->anchored;
+    return !(*s & SHENG64_STATE_DEAD);
+}
+
+char nfaExecSheng64_queueInitState(const struct NFA *nfa, struct mq *q) {
+    assert(nfa->scratchStateSize == 1);
+
+    /* starting in floating state */
+    const struct sheng64 *sh = get_sheng64(nfa);
+    *(u8 *)q->state = sh->floating;
+    DEBUG_PRINTF("starting in floating state\n");
+    return 0;
+}
+
+char nfaExecSheng64_queueCompressState(UNUSED const struct NFA *nfa,
+                                       const struct mq *q, UNUSED s64a loc) {
+    void *dest = q->streamState;
+    const void *src = q->state;
+    assert(nfa->scratchStateSize == 1);
+    assert(nfa->streamStateSize == 1);
+    *(u8 *)dest = *(const u8 *)src;
+    return 0;
+}
+
+char nfaExecSheng64_expandState(UNUSED const struct NFA *nfa, void *dest,
+                                const void *src, UNUSED u64a offset,
+                                UNUSED u8 key) {
+    assert(nfa->scratchStateSize == 1);
+    assert(nfa->streamStateSize == 1);
+    *(u8 *)dest = *(const u8 *)src;
+    return 0;
+}
 #endif // end of HAVE_AVX512VBMI
index d017bbbc3ed8b2175ce52f84a040ebc1c85260d3..7b90e3034f05af7e1d80499b079de4b59323a7b8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Intel Corporation
+ * Copyright (c) 2016-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -82,7 +82,33 @@ char nfaExecSheng32_reportCurrent(const struct NFA *n, struct mq *q);
 
 char nfaExecSheng32_B(const struct NFA *n, u64a offset, const u8 *buffer,
                       size_t length, NfaCallback cb, void *context);
+
+#define nfaExecSheng64_B_Reverse NFA_API_NO_IMPL
+#define nfaExecSheng64_zombie_status NFA_API_ZOMBIE_NO_IMPL
+
+char nfaExecSheng64_Q(const struct NFA *n, struct mq *q, s64a end);
+char nfaExecSheng64_Q2(const struct NFA *n, struct mq *q, s64a end);
+char nfaExecSheng64_QR(const struct NFA *n, struct mq *q, ReportID report);
+char nfaExecSheng64_inAccept(const struct NFA *n, ReportID report,
+                             struct mq *q);
+char nfaExecSheng64_inAnyAccept(const struct NFA *n, struct mq *q);
+char nfaExecSheng64_queueInitState(const struct NFA *nfa, struct mq *q);
+char nfaExecSheng64_queueCompressState(const struct NFA *nfa,
+                                       const struct mq *q, s64a loc);
+char nfaExecSheng64_expandState(const struct NFA *nfa, void *dest,
+                                const void *src, u64a offset, u8 key);
+char nfaExecSheng64_initCompressedState(const struct NFA *nfa, u64a offset,
+                                        void *state, u8 key);
+char nfaExecSheng64_testEOD(const struct NFA *nfa, const char *state,
+                            const char *streamState, u64a offset,
+                            NfaCallback callback, void *context);
+char nfaExecSheng64_reportCurrent(const struct NFA *n, struct mq *q);
+
+char nfaExecSheng64_B(const struct NFA *n, u64a offset, const u8 *buffer,
+                      size_t length, NfaCallback cb, void *context);
+
 #else // !HAVE_AVX512VBMI
+
 #define nfaExecSheng32_B_Reverse NFA_API_NO_IMPL
 #define nfaExecSheng32_zombie_status NFA_API_ZOMBIE_NO_IMPL
 #define nfaExecSheng32_Q NFA_API_NO_IMPL
@@ -97,6 +123,21 @@ char nfaExecSheng32_B(const struct NFA *n, u64a offset, const u8 *buffer,
 #define nfaExecSheng32_testEOD NFA_API_NO_IMPL
 #define nfaExecSheng32_reportCurrent NFA_API_NO_IMPL
 #define nfaExecSheng32_B NFA_API_NO_IMPL
+
+#define nfaExecSheng64_B_Reverse NFA_API_NO_IMPL
+#define nfaExecSheng64_zombie_status NFA_API_ZOMBIE_NO_IMPL
+#define nfaExecSheng64_Q NFA_API_NO_IMPL
+#define nfaExecSheng64_Q2 NFA_API_NO_IMPL
+#define nfaExecSheng64_QR NFA_API_NO_IMPL
+#define nfaExecSheng64_inAccept NFA_API_NO_IMPL
+#define nfaExecSheng64_inAnyAccept NFA_API_NO_IMPL
+#define nfaExecSheng64_queueInitState NFA_API_NO_IMPL
+#define nfaExecSheng64_queueCompressState NFA_API_NO_IMPL
+#define nfaExecSheng64_expandState NFA_API_NO_IMPL
+#define nfaExecSheng64_initCompressedState NFA_API_NO_IMPL
+#define nfaExecSheng64_testEOD NFA_API_NO_IMPL
+#define nfaExecSheng64_reportCurrent NFA_API_NO_IMPL
+#define nfaExecSheng64_B NFA_API_NO_IMPL
 #endif // end of HAVE_AVX512VBMI
 
 #endif /* SHENG_H_ */
index ddf76f35743fb31ff5c03ab09597d4eac0de8b5b..390af7522122699f0be19e118a5cbd58c63a43e3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Intel Corporation
+ * Copyright (c) 2016-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -37,46 +37,55 @@ u8 isDeadState(const u8 a) {
     return a & SHENG_STATE_DEAD;
 }
 
-#if defined(HAVE_AVX512VBMI)
 static really_inline
-u8 isDeadState32(const u8 a) {
-    return a & SHENG32_STATE_DEAD;
+u8 isAcceptState(const u8 a) {
+    return a & SHENG_STATE_ACCEPT;
 }
-#endif
 
 static really_inline
-u8 isAcceptState(const u8 a) {
-    return a & SHENG_STATE_ACCEPT;
+u8 isAccelState(const u8 a) {
+    return a & SHENG_STATE_ACCEL;
+}
+
+static really_inline
+u8 hasInterestingStates(const u8 a, const u8 b, const u8 c, const u8 d) {
+    return (a | b | c | d) & (SHENG_STATE_FLAG_MASK);
 }
 
 #if defined(HAVE_AVX512VBMI)
 static really_inline
-u8 isAcceptState32(const u8 a) {
-    return a & SHENG32_STATE_ACCEPT;
+u8 isDeadState32(const u8 a) {
+    return a & SHENG32_STATE_DEAD;
 }
-#endif
 
 static really_inline
-u8 isAccelState(const u8 a) {
-    return a & SHENG_STATE_ACCEL;
+u8 isAcceptState32(const u8 a) {
+    return a & SHENG32_STATE_ACCEPT;
 }
 
-#if defined(HAVE_AVX512VBMI)
 static really_inline
 u8 isAccelState32(const u8 a) {
     return a & SHENG32_STATE_ACCEL;
 }
-#endif
 
 static really_inline
-u8 hasInterestingStates(const u8 a, const u8 b, const u8 c, const u8 d) {
-    return (a | b | c | d) & (SHENG_STATE_FLAG_MASK);
+u8 hasInterestingStates32(const u8 a, const u8 b, const u8 c, const u8 d) {
+    return (a | b | c | d) & (SHENG32_STATE_FLAG_MASK);
 }
 
-#if defined(HAVE_AVX512VBMI)
 static really_inline
-u8 hasInterestingStates32(const u8 a, const u8 b, const u8 c, const u8 d) {
-    return (a | b | c | d) & (SHENG32_STATE_FLAG_MASK);
+u8 isDeadState64(const u8 a) {
+    return a & SHENG64_STATE_DEAD;
+}
+
+static really_inline
+u8 isAcceptState64(const u8 a) {
+    return a & SHENG64_STATE_ACCEPT;
+}
+
+static really_inline
+u8 hasInterestingStates64(const u8 a, const u8 b, const u8 c, const u8 d) {
+    return (a | b | c | d) & (SHENG64_STATE_FLAG_MASK);
 }
 #endif
 
@@ -103,6 +112,9 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define SHENG32_IMPL sheng32_cod
 #define DEAD_FUNC32 isDeadState32
 #define ACCEPT_FUNC32 isAcceptState32
+#define SHENG64_IMPL sheng64_cod
+#define DEAD_FUNC64 isDeadState64
+#define ACCEPT_FUNC64 isAcceptState64
 #endif
 #define STOP_AT_MATCH 0
 #include "sheng_impl.h"
@@ -113,6 +125,9 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef SHENG32_IMPL
 #undef DEAD_FUNC32
 #undef ACCEPT_FUNC32
+#undef SHENG64_IMPL
+#undef DEAD_FUNC64
+#undef ACCEPT_FUNC64
 #endif
 #undef STOP_AT_MATCH
 
@@ -124,6 +139,9 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define SHENG32_IMPL sheng32_co
 #define DEAD_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 isAcceptState32
+#define SHENG64_IMPL sheng64_co
+#define DEAD_FUNC64 dummyFunc
+#define ACCEPT_FUNC64 isAcceptState64
 #endif
 #define STOP_AT_MATCH 0
 #include "sheng_impl.h"
@@ -134,6 +152,9 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef SHENG32_IMPL
 #undef DEAD_FUNC32
 #undef ACCEPT_FUNC32
+#undef SHENG64_IMPL
+#undef DEAD_FUNC64
+#undef ACCEPT_FUNC64
 #endif
 #undef STOP_AT_MATCH
 
@@ -145,6 +166,9 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define SHENG32_IMPL sheng32_samd
 #define DEAD_FUNC32 isDeadState32
 #define ACCEPT_FUNC32 isAcceptState32
+#define SHENG64_IMPL sheng64_samd
+#define DEAD_FUNC64 isDeadState64
+#define ACCEPT_FUNC64 isAcceptState64
 #endif
 #define STOP_AT_MATCH 1
 #include "sheng_impl.h"
@@ -155,6 +179,9 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef SHENG32_IMPL
 #undef DEAD_FUNC32
 #undef ACCEPT_FUNC32
+#undef SHENG64_IMPL
+#undef DEAD_FUNC64
+#undef ACCEPT_FUNC64
 #endif
 #undef STOP_AT_MATCH
 
@@ -166,6 +193,9 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define SHENG32_IMPL sheng32_sam
 #define DEAD_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 isAcceptState32
+#define SHENG64_IMPL sheng64_sam
+#define DEAD_FUNC64 dummyFunc
+#define ACCEPT_FUNC64 isAcceptState64
 #endif
 #define STOP_AT_MATCH 1
 #include "sheng_impl.h"
@@ -176,6 +206,9 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef SHENG32_IMPL
 #undef DEAD_FUNC32
 #undef ACCEPT_FUNC32
+#undef SHENG64_IMPL
+#undef DEAD_FUNC64
+#undef ACCEPT_FUNC64
 #endif
 #undef STOP_AT_MATCH
 
@@ -187,6 +220,9 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define SHENG32_IMPL sheng32_nmd
 #define DEAD_FUNC32 isDeadState32
 #define ACCEPT_FUNC32 dummyFunc
+#define SHENG64_IMPL sheng64_nmd
+#define DEAD_FUNC64 isDeadState64
+#define ACCEPT_FUNC64 dummyFunc
 #endif
 #define STOP_AT_MATCH 0
 #include "sheng_impl.h"
@@ -197,6 +233,9 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef SHENG32_IMPL
 #undef DEAD_FUNC32
 #undef ACCEPT_FUNC32
+#undef SHENG64_IMPL
+#undef DEAD_FUNC64
+#undef ACCEPT_FUNC64
 #endif
 #undef STOP_AT_MATCH
 
@@ -208,6 +247,9 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define SHENG32_IMPL sheng32_nm
 #define DEAD_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 dummyFunc
+#define SHENG64_IMPL sheng64_nm
+#define DEAD_FUNC64 dummyFunc
+#define ACCEPT_FUNC64 dummyFunc
 #endif
 #define STOP_AT_MATCH 0
 #include "sheng_impl.h"
@@ -218,6 +260,9 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef SHENG32_IMPL
 #undef DEAD_FUNC32
 #undef ACCEPT_FUNC32
+#undef SHENG64_IMPL
+#undef DEAD_FUNC64
+#undef ACCEPT_FUNC64
 #endif
 #undef STOP_AT_MATCH
 
@@ -240,6 +285,7 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define INNER_ACCEL_FUNC32 isAccelState32
 #define OUTER_ACCEL_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 isAcceptState32
+#define NO_SHENG64_IMPL
 #endif
 #define STOP_AT_MATCH 0
 #include "sheng_impl4.h"
@@ -258,6 +304,7 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef INNER_ACCEL_FUNC32
 #undef OUTER_ACCEL_FUNC32
 #undef ACCEPT_FUNC32
+#undef NO_SHENG64_IMPL
 #endif
 #undef STOP_AT_MATCH
 
@@ -277,6 +324,11 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define INNER_ACCEL_FUNC32 dummyFunc
 #define OUTER_ACCEL_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 isAcceptState32
+#define SHENG64_IMPL sheng64_4_cod
+#define INTERESTING_FUNC64 hasInterestingStates64
+#define INNER_DEAD_FUNC64 isDeadState64
+#define OUTER_DEAD_FUNC64 dummyFunc
+#define ACCEPT_FUNC64 isAcceptState64
 #endif
 #define STOP_AT_MATCH 0
 #include "sheng_impl4.h"
@@ -295,6 +347,11 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef INNER_ACCEL_FUNC32
 #undef OUTER_ACCEL_FUNC32
 #undef ACCEPT_FUNC32
+#undef SHENG64_IMPL
+#undef INTERESTING_FUNC64
+#undef INNER_DEAD_FUNC64
+#undef OUTER_DEAD_FUNC64
+#undef ACCEPT_FUNC64
 #endif
 #undef STOP_AT_MATCH
 
@@ -314,6 +371,7 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define INNER_ACCEL_FUNC32 isAccelState32
 #define OUTER_ACCEL_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 isAcceptState32
+#define NO_SHENG64_IMPL
 #endif
 #define STOP_AT_MATCH 0
 #include "sheng_impl4.h"
@@ -332,6 +390,7 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef INNER_ACCEL_FUNC32
 #undef OUTER_ACCEL_FUNC32
 #undef ACCEPT_FUNC32
+#undef NO_SHENG64_IMPL
 #endif
 #undef STOP_AT_MATCH
 
@@ -351,6 +410,11 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define INNER_ACCEL_FUNC32 dummyFunc
 #define OUTER_ACCEL_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 isAcceptState32
+#define SHENG64_IMPL sheng64_4_co
+#define INTERESTING_FUNC64 hasInterestingStates64
+#define INNER_DEAD_FUNC64 dummyFunc
+#define OUTER_DEAD_FUNC64 dummyFunc
+#define ACCEPT_FUNC64 isAcceptState64
 #endif
 #define STOP_AT_MATCH 0
 #include "sheng_impl4.h"
@@ -369,6 +433,11 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef INNER_ACCEL_FUNC32
 #undef OUTER_ACCEL_FUNC32
 #undef ACCEPT_FUNC32
+#undef SHENG64_IMPL
+#undef INTERESTING_FUNC64
+#undef INNER_DEAD_FUNC64
+#undef OUTER_DEAD_FUNC64
+#undef ACCEPT_FUNC64
 #endif
 #undef STOP_AT_MATCH
 
@@ -388,6 +457,7 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define INNER_ACCEL_FUNC32 isAccelState32
 #define OUTER_ACCEL_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 isAcceptState32
+#define NO_SHENG64_IMPL
 #endif
 #define STOP_AT_MATCH 1
 #include "sheng_impl4.h"
@@ -406,6 +476,7 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef INNER_ACCEL_FUNC32
 #undef OUTER_ACCEL_FUNC32
 #undef ACCEPT_FUNC32
+#undef NO_SHENG64_IMPL
 #endif
 #undef STOP_AT_MATCH
 
@@ -425,6 +496,11 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define INNER_ACCEL_FUNC32 dummyFunc
 #define OUTER_ACCEL_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 isAcceptState32
+#define SHENG64_IMPL sheng64_4_samd
+#define INTERESTING_FUNC64 hasInterestingStates64
+#define INNER_DEAD_FUNC64 isDeadState64
+#define OUTER_DEAD_FUNC64 dummyFunc
+#define ACCEPT_FUNC64 isAcceptState64
 #endif
 #define STOP_AT_MATCH 1
 #include "sheng_impl4.h"
@@ -443,6 +519,11 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef INNER_ACCEL_FUNC32
 #undef OUTER_ACCEL_FUNC32
 #undef ACCEPT_FUNC32
+#undef SHENG64_IMPL
+#undef INTERESTING_FUNC64
+#undef INNER_DEAD_FUNC64
+#undef OUTER_DEAD_FUNC64
+#undef ACCEPT_FUNC64
 #endif
 #undef STOP_AT_MATCH
 
@@ -462,6 +543,7 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define INNER_ACCEL_FUNC32 isAccelState32
 #define OUTER_ACCEL_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 isAcceptState32
+#define NO_SHENG64_IMPL
 #endif
 #define STOP_AT_MATCH 1
 #include "sheng_impl4.h"
@@ -480,6 +562,7 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef INNER_ACCEL_FUNC32
 #undef OUTER_ACCEL_FUNC32
 #undef ACCEPT_FUNC32
+#undef NO_SHENG64_IMPL
 #endif
 #undef STOP_AT_MATCH
 
@@ -499,6 +582,11 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define INNER_ACCEL_FUNC32 dummyFunc
 #define OUTER_ACCEL_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 isAcceptState32
+#define SHENG64_IMPL sheng64_4_sam
+#define INTERESTING_FUNC64 hasInterestingStates64
+#define INNER_DEAD_FUNC64 dummyFunc
+#define OUTER_DEAD_FUNC64 dummyFunc
+#define ACCEPT_FUNC64 isAcceptState64
 #endif
 #define STOP_AT_MATCH 1
 #include "sheng_impl4.h"
@@ -517,6 +605,11 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef INNER_ACCEL_FUNC32
 #undef OUTER_ACCEL_FUNC32
 #undef ACCEPT_FUNC32
+#undef SHENG64_IMPL
+#undef INTERESTING_FUNC64
+#undef INNER_DEAD_FUNC64
+#undef OUTER_DEAD_FUNC64
+#undef ACCEPT_FUNC64
 #endif
 #undef STOP_AT_MATCH
 
@@ -538,6 +631,7 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define INNER_ACCEL_FUNC32 dummyFunc
 #define OUTER_ACCEL_FUNC32 isAccelState32
 #define ACCEPT_FUNC32 dummyFunc
+#define NO_SHENG64_IMPL
 #endif
 #define STOP_AT_MATCH 0
 #include "sheng_impl4.h"
@@ -556,6 +650,7 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef INNER_ACCEL_FUNC32
 #undef OUTER_ACCEL_FUNC32
 #undef ACCEPT_FUNC32
+#undef NO_SHENG64_IMPL
 #endif
 #undef STOP_AT_MATCH
 
@@ -575,6 +670,11 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define INNER_ACCEL_FUNC32 dummyFunc
 #define OUTER_ACCEL_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 dummyFunc
+#define SHENG64_IMPL sheng64_4_nmd
+#define INTERESTING_FUNC64 dummyFunc4
+#define INNER_DEAD_FUNC64 dummyFunc
+#define OUTER_DEAD_FUNC64 isDeadState64
+#define ACCEPT_FUNC64 dummyFunc
 #endif
 #define STOP_AT_MATCH 0
 #include "sheng_impl4.h"
@@ -593,6 +693,11 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef INNER_ACCEL_FUNC32
 #undef OUTER_ACCEL_FUNC32
 #undef ACCEPT_FUNC32
+#undef SHENG64_IMPL
+#undef INTERESTING_FUNC64
+#undef INNER_DEAD_FUNC64
+#undef OUTER_DEAD_FUNC64
+#undef ACCEPT_FUNC64
 #endif
 #undef STOP_AT_MATCH
 
@@ -615,6 +720,11 @@ u8 dummyFunc(UNUSED const u8 a) {
 #define INNER_ACCEL_FUNC32 dummyFunc
 #define OUTER_ACCEL_FUNC32 dummyFunc
 #define ACCEPT_FUNC32 dummyFunc
+#define SHENG64_IMPL sheng64_4_nm
+#define INTERESTING_FUNC64 dummyFunc4
+#define INNER_DEAD_FUNC64 dummyFunc
+#define OUTER_DEAD_FUNC64 dummyFunc
+#define ACCEPT_FUNC64 dummyFunc
 #endif
 #define STOP_AT_MATCH 0
 #include "sheng_impl4.h"
@@ -633,6 +743,11 @@ u8 dummyFunc(UNUSED const u8 a) {
 #undef INNER_ACCEL_FUNC32
 #undef OUTER_ACCEL_FUNC32
 #undef ACCEPT_FUNC32
+#undef SHENG64_IMPL
+#undef INTERESTING_FUNC64
+#undef INNER_DEAD_FUNC64
+#undef OUTER_DEAD_FUNC64
+#undef ACCEPT_FUNC64
 #endif
 #undef STOP_AT_MATCH
 
index 2fc3b02300f34d814dbe1f1ade39268684939265..17f929abdac91d13803ed4cee675175f4bb43723 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, Intel Corporation
+ * Copyright (c) 2016-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -157,4 +157,65 @@ char SHENG32_IMPL(u8 *state, NfaCallback cb, void *ctxt,
     *scan_end = cur_buf;
     return MO_CONTINUE_MATCHING;
 }
+
+static really_inline
+char SHENG64_IMPL(u8 *state, NfaCallback cb, void *ctxt,
+                  const struct sheng64 *s,
+                  u8 *const cached_accept_state,
+                  ReportID *const cached_accept_id,
+                  u8 single, u64a base_offset, const u8 *buf, const u8 *start,
+                  const u8 *end, const u8 **scan_end) {
+    DEBUG_PRINTF("Starting DFA execution in state %u\n",
+                 *state & SHENG64_STATE_MASK);
+    const u8 *cur_buf = start;
+    if (DEAD_FUNC64(*state)) {
+        DEBUG_PRINTF("Dead on arrival\n");
+        *scan_end = end;
+        return MO_CONTINUE_MATCHING;
+    }
+    DEBUG_PRINTF("Scanning %lli bytes\n", (s64a)(end - start));
+
+    m512 cur_state = set64x8(*state);
+    const m512 *masks = s->succ_masks;
+
+    while (likely(cur_buf != end)) {
+        const u8 c = *cur_buf;
+        const m512 succ_mask = masks[c];
+        cur_state = vpermb512(cur_state, succ_mask);
+        const u8 tmp = movd512(cur_state);
+
+        DEBUG_PRINTF("c: %02hhx '%c'\n", c, ourisprint(c) ? c : '?');
+        DEBUG_PRINTF("s: %u (flag: %u)\n", tmp & SHENG64_STATE_MASK,
+                     tmp & SHENG64_STATE_FLAG_MASK);
+
+        if (unlikely(ACCEPT_FUNC64(tmp))) {
+            DEBUG_PRINTF("Accept state %u reached\n", tmp & SHENG64_STATE_MASK);
+            u64a match_offset = base_offset + (cur_buf - buf) + 1;
+            DEBUG_PRINTF("Match @ %llu\n", match_offset);
+            if (STOP_AT_MATCH) {
+                DEBUG_PRINTF("Stopping at match @ %lli\n",
+                             (u64a)(cur_buf - start));
+                *state = tmp;
+                *scan_end = cur_buf;
+                return MO_MATCHES_PENDING;
+            }
+            if (single) {
+                if (fireSingleReport(cb, ctxt, s->report, match_offset) ==
+                    MO_HALT_MATCHING) {
+                    return MO_HALT_MATCHING;
+                }
+            } else {
+                if (fireReports64(s, cb, ctxt, tmp, match_offset,
+                                  cached_accept_state, cached_accept_id,
+                                  0) == MO_HALT_MATCHING) {
+                    return MO_HALT_MATCHING;
+                }
+            }
+        }
+        cur_buf++;
+    }
+    *state = movd512(cur_state);
+    *scan_end = cur_buf;
+    return MO_CONTINUE_MATCHING;
+}
 #endif
index 063569128e3d7179d6389bdb1d1ae13e4eed7ee5..a2c325fdd3cffa3667e3d0fe18a143b5aef1af3e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, Intel Corporation
+ * Copyright (c) 2016-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -521,4 +521,191 @@ char SHENG32_IMPL(u8 *state, NfaCallback cb, void *ctxt,
     *scan_end = cur_buf;
     return MO_CONTINUE_MATCHING;
 }
+
+#ifndef NO_SHENG64_IMPL
+static really_inline
+char SHENG64_IMPL(u8 *state, NfaCallback cb, void *ctxt,
+                  const struct sheng64 *s,
+                  u8 *const cached_accept_state,
+                  ReportID *const cached_accept_id,
+                  u8 single, u64a base_offset, const u8 *buf, const u8 *start,
+                  const u8 *end, const u8 **scan_end) {
+    DEBUG_PRINTF("Starting DFAx4 execution in state %u\n",
+                 *state & SHENG64_STATE_MASK);
+    const u8 *cur_buf = start;
+    base_offset++;
+    DEBUG_PRINTF("Scanning %llu bytes\n", (u64a)(end - start));
+
+    if (INNER_DEAD_FUNC64(*state) || OUTER_DEAD_FUNC64(*state)) {
+        DEBUG_PRINTF("Dead on arrival\n");
+        *scan_end = end;
+        return MO_CONTINUE_MATCHING;
+    }
+
+    m512 cur_state = set64x8(*state);
+    const m512 *masks = s->succ_masks;
+
+    while (likely(end - cur_buf >= 4)) {
+        const u8 *b1 = cur_buf;
+        const u8 *b2 = cur_buf + 1;
+        const u8 *b3 = cur_buf + 2;
+        const u8 *b4 = cur_buf + 3;
+        const u8 c1 = *b1;
+        const u8 c2 = *b2;
+        const u8 c3 = *b3;
+        const u8 c4 = *b4;
+
+        const m512 succ_mask1 = masks[c1];
+        cur_state = vpermb512(cur_state, succ_mask1);
+        const u8 a1 = movd512(cur_state);
+
+        const m512 succ_mask2 = masks[c2];
+        cur_state = vpermb512(cur_state, succ_mask2);
+        const u8 a2 = movd512(cur_state);
+
+        const m512 succ_mask3 = masks[c3];
+        cur_state = vpermb512(cur_state, succ_mask3);
+        const u8 a3 = movd512(cur_state);
+
+        const m512 succ_mask4 = masks[c4];
+        cur_state = vpermb512(cur_state, succ_mask4);
+        const u8 a4 = movd512(cur_state);
+
+        DEBUG_PRINTF("c: %02hhx '%c'\n", c1, ourisprint(c1) ? c1 : '?');
+        DEBUG_PRINTF("s: %u (flag: %u)\n", a1 & SHENG64_STATE_MASK,
+                     a1 & SHENG64_STATE_FLAG_MASK);
+
+        DEBUG_PRINTF("c: %02hhx '%c'\n", c2, ourisprint(c2) ? c2 : '?');
+        DEBUG_PRINTF("s: %u (flag: %u)\n", a2 & SHENG64_STATE_MASK,
+                     a2 & SHENG64_STATE_FLAG_MASK);
+
+        DEBUG_PRINTF("c: %02hhx '%c'\n", c3, ourisprint(c3) ? c3 : '?');
+        DEBUG_PRINTF("s: %u (flag: %u)\n", a3 & SHENG64_STATE_MASK,
+                     a3 & SHENG64_STATE_FLAG_MASK);
+
+        DEBUG_PRINTF("c: %02hhx '%c'\n", c4, ourisprint(c4) ? c4 : '?');
+        DEBUG_PRINTF("s: %u (flag: %u)\n", a4 & SHENG64_STATE_MASK,
+                     a4 & SHENG64_STATE_FLAG_MASK);
+
+        if (unlikely(INTERESTING_FUNC64(a1, a2, a3, a4))) {
+            if (ACCEPT_FUNC64(a1)) {
+                u64a match_offset = base_offset + b1 - buf;
+                DEBUG_PRINTF("Accept state %u reached\n",
+                             a1 & SHENG64_STATE_MASK);
+                DEBUG_PRINTF("Match @ %llu\n", match_offset);
+                if (STOP_AT_MATCH) {
+                    DEBUG_PRINTF("Stopping at match @ %lli\n",
+                                 (s64a)(b1 - start));
+                    *scan_end = b1;
+                    *state = a1;
+                    return MO_MATCHES_PENDING;
+                }
+                if (single) {
+                    if (fireSingleReport(cb, ctxt, s->report, match_offset) ==
+                        MO_HALT_MATCHING) {
+                        return MO_HALT_MATCHING;
+                    }
+                } else {
+                    if (fireReports64(s, cb, ctxt, a1, match_offset,
+                                      cached_accept_state, cached_accept_id,
+                                      0) == MO_HALT_MATCHING) {
+                        return MO_HALT_MATCHING;
+                    }
+                }
+            }
+            if (ACCEPT_FUNC64(a2)) {
+                u64a match_offset = base_offset + b2 - buf;
+                DEBUG_PRINTF("Accept state %u reached\n",
+                             a2 & SHENG64_STATE_MASK);
+                DEBUG_PRINTF("Match @ %llu\n", match_offset);
+                if (STOP_AT_MATCH) {
+                    DEBUG_PRINTF("Stopping at match @ %lli\n",
+                                 (s64a)(b2 - start));
+                    *scan_end = b2;
+                    *state = a2;
+                    return MO_MATCHES_PENDING;
+                }
+                if (single) {
+                    if (fireSingleReport(cb, ctxt, s->report, match_offset) ==
+                        MO_HALT_MATCHING) {
+                        return MO_HALT_MATCHING;
+                    }
+                } else {
+                    if (fireReports64(s, cb, ctxt, a2, match_offset,
+                                      cached_accept_state, cached_accept_id,
+                                      0) == MO_HALT_MATCHING) {
+                        return MO_HALT_MATCHING;
+                    }
+                }
+            }
+            if (ACCEPT_FUNC64(a3)) {
+                u64a match_offset = base_offset + b3 - buf;
+                DEBUG_PRINTF("Accept state %u reached\n",
+                             a3 & SHENG64_STATE_MASK);
+                DEBUG_PRINTF("Match @ %llu\n", match_offset);
+                if (STOP_AT_MATCH) {
+                    DEBUG_PRINTF("Stopping at match @ %lli\n",
+                                 (s64a)(b3 - start));
+                    *scan_end = b3;
+                    *state = a3;
+                    return MO_MATCHES_PENDING;
+                }
+                if (single) {
+                    if (fireSingleReport(cb, ctxt, s->report, match_offset) ==
+                        MO_HALT_MATCHING) {
+                        return MO_HALT_MATCHING;
+                    }
+                } else {
+                    if (fireReports64(s, cb, ctxt, a3, match_offset,
+                                      cached_accept_state, cached_accept_id,
+                                      0) == MO_HALT_MATCHING) {
+                        return MO_HALT_MATCHING;
+                    }
+                }
+            }
+            if (ACCEPT_FUNC64(a4)) {
+                u64a match_offset = base_offset + b4 - buf;
+                DEBUG_PRINTF("Accept state %u reached\n",
+                             a4 & SHENG64_STATE_MASK);
+                DEBUG_PRINTF("Match @ %llu\n", match_offset);
+                if (STOP_AT_MATCH) {
+                    DEBUG_PRINTF("Stopping at match @ %lli\n",
+                                 (s64a)(b4 - start));
+                    *scan_end = b4;
+                    *state = a4;
+                    return MO_MATCHES_PENDING;
+                }
+                if (single) {
+                    if (fireSingleReport(cb, ctxt, s->report, match_offset) ==
+                        MO_HALT_MATCHING) {
+                        return MO_HALT_MATCHING;
+                    }
+                } else {
+                    if (fireReports64(s, cb, ctxt, a4, match_offset,
+                                      cached_accept_state, cached_accept_id,
+                                      0) == MO_HALT_MATCHING) {
+                        return MO_HALT_MATCHING;
+                    }
+                }
+            }
+            if (INNER_DEAD_FUNC64(a4)) {
+                DEBUG_PRINTF("Dead state reached @ %lli\n", (s64a)(b4 - buf));
+                *scan_end = end;
+                *state = a4;
+                return MO_CONTINUE_MATCHING;
+            }
+        }
+        if (OUTER_DEAD_FUNC64(a4)) {
+            DEBUG_PRINTF("Dead state reached @ %lli\n", (s64a)(cur_buf - buf));
+            *scan_end = end;
+            *state = a4;
+            return MO_CONTINUE_MATCHING;
+        }
+        cur_buf += 4;
+    }
+    *state = movd512(cur_state);
+    *scan_end = cur_buf;
+    return MO_CONTINUE_MATCHING;
+}
+#endif // !NO_SHENG64_IMPL
 #endif
index 68a1680f18c4919d582eb20ef7fdf30616437d92..b3133e703cddcb83d6cffe5312b7ce64b171e5d0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Intel Corporation
+ * Copyright (c) 2016-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
 #define SHENG32_STATE_ACCEL 0x80
 #define SHENG32_STATE_MASK 0x1F
 #define SHENG32_STATE_FLAG_MASK 0xE0
+
+#define SHENG64_STATE_ACCEPT 0x40
+#define SHENG64_STATE_DEAD 0x80
+#define SHENG64_STATE_MASK 0x3F
+#define SHENG64_STATE_FLAG_MASK 0xC0
 #endif
 
 #define SHENG_FLAG_SINGLE_REPORT 0x1
@@ -88,6 +93,19 @@ struct sheng32 {
     u8 flags;
     ReportID report;
 };
+
+struct sheng64 {
+    m512 succ_masks[256];
+    u32 length;
+    u32 aux_offset;
+    u32 report_offset;
+    u32 accel_offset;
+    u8 n_states;
+    u8 anchored;
+    u8 floating;
+    u8 flags;
+    ReportID report;
+};
 #endif
 
 #endif /* SHENG_INTERNAL_H_ */
index f968bf59e771b0577cc6bafeeb9f377d56689158..485d6b64e7127b10ad5db90e48219fe5cd07a5df 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, Intel Corporation
+ * Copyright (c) 2016-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -312,6 +312,17 @@ void dumpShuffleMask32(const u8 chr, const u8 *buf, unsigned sz) {
     }
     DEBUG_PRINTF("chr %3u: %s\n", chr, o.str().c_str());
 }
+
+static really_inline
+void dumpShuffleMask64(const u8 chr, const u8 *buf, unsigned sz) {
+    stringstream o;
+
+    for (unsigned i = 0; i < sz; i++) {
+        o.width(2);
+        o << (buf[i] & SHENG64_STATE_MASK) << " ";
+    }
+    DEBUG_PRINTF("chr %3u: %s\n", chr, o.str().c_str());
+}
 #endif
 
 static
@@ -361,6 +372,19 @@ u8 getShengState<sheng32>(dstate &state, dfa_info &info,
     }
     return s;
 }
+
+template <>
+u8 getShengState<sheng64>(dstate &state, dfa_info &info,
+                          UNUSED map<dstate_id_t, AccelScheme> &accelInfo) {
+    u8 s = state.impl_id;
+    if (!state.reports.empty()) {
+        s |= SHENG64_STATE_ACCEPT;
+    }
+    if (info.isDead(state)) {
+        s |= SHENG64_STATE_DEAD;
+    }
+    return s;
+}
 #endif
 
 template <typename T>
@@ -444,6 +468,31 @@ void populateBasicInfo<sheng32>(struct NFA *n, dfa_info &info,
     s->anchored = getShengState<sheng32>(info.anchored, info, accelInfo);
     s->floating = getShengState<sheng32>(info.floating, info, accelInfo);
 }
+
+template <>
+void populateBasicInfo<sheng64>(struct NFA *n, dfa_info &info,
+                                map<dstate_id_t, AccelScheme> &accelInfo,
+                                u32 aux_offset, u32 report_offset,
+                                u32 accel_offset, u32 total_size,
+                                u32 dfa_size) {
+    n->length = total_size;
+    n->scratchStateSize = 1;
+    n->streamStateSize = 1;
+    n->nPositions = info.size();
+    n->type = SHENG_NFA_64;
+    n->flags |= info.raw.hasEodReports() ? NFA_ACCEPTS_EOD : 0;
+
+    sheng64 *s = (sheng64 *)getMutableImplNfa(n);
+    s->aux_offset = aux_offset;
+    s->report_offset = report_offset;
+    s->accel_offset = accel_offset;
+    s->n_states = info.size();
+    s->length = dfa_size;
+    s->flags |= info.can_die ? SHENG_FLAG_CAN_DIE : 0;
+
+    s->anchored = getShengState<sheng64>(info.anchored, info, accelInfo);
+    s->floating = getShengState<sheng64>(info.floating, info, accelInfo);
+}
 #endif
 
 template <typename T>
@@ -506,12 +555,13 @@ void fillSingleReport(NFA *n, ReportID r_id) {
 
 template <typename T>
 static
-void createShuffleMasks(T *s, dfa_info &info,
+bool createShuffleMasks(T *s, dfa_info &info,
                         map<dstate_id_t, AccelScheme> &accelInfo) {
+    return true;
 }
 
 template <>
-void createShuffleMasks<sheng>(sheng *s, dfa_info &info,
+bool createShuffleMasks<sheng>(sheng *s, dfa_info &info,
                                map<dstate_id_t, AccelScheme> &accelInfo) {
     for (u16 chr = 0; chr < 256; chr++) {
         u8 buf[16] = {0};
@@ -526,11 +576,12 @@ void createShuffleMasks<sheng>(sheng *s, dfa_info &info,
 #endif
         memcpy(&s->shuffle_masks[chr], buf, sizeof(m128));
     }
+    return true;
 }
 
 #if defined(HAVE_AVX512VBMI)
 template <>
-void createShuffleMasks<sheng32>(sheng32 *s, dfa_info &info,
+bool createShuffleMasks<sheng32>(sheng32 *s, dfa_info &info,
                                  map<dstate_id_t, AccelScheme> &accelInfo) {
     for (u16 chr = 0; chr < 256; chr++) {
         u8 buf[64] = {0};
@@ -547,6 +598,31 @@ void createShuffleMasks<sheng32>(sheng32 *s, dfa_info &info,
 #endif
         memcpy(&s->succ_masks[chr], buf, sizeof(m512));
     }
+    return true;
+}
+
+template <>
+bool createShuffleMasks<sheng64>(sheng64 *s, dfa_info &info,
+                                 map<dstate_id_t, AccelScheme> &accelInfo) {
+    for (u16 chr = 0; chr < 256; chr++) {
+        u8 buf[64] = {0};
+
+        assert(info.size() <= 64);
+        for (dstate_id_t idx = 0; idx < info.size(); idx++) {
+            auto &succ_state = info.next(idx, chr);
+
+            if (accelInfo.find(info.raw_id(succ_state.impl_id))
+                != accelInfo.end()) {
+                return false;
+            }
+            buf[idx] = getShengState<sheng64>(succ_state, info, accelInfo);
+        }
+#ifdef DEBUG
+        dumpShuffleMask64(chr, buf, sizeof(buf));
+#endif
+        memcpy(&s->succ_masks[chr], buf, sizeof(m512));
+    }
+    return true;
 }
 #endif
 
@@ -619,7 +695,9 @@ bytecode_ptr<NFA> shengCompile_int(raw_dfa &raw, const CompileContext &cc,
         fillAccelOut(accelInfo, accel_states);
     }
 
-    createShuffleMasks<T>((T *)getMutableImplNfa(nfa.get()), info, accelInfo);
+    if (!createShuffleMasks<T>((T *)getMutableImplNfa(nfa.get()), info, accelInfo)) {
+        return nullptr;
+    }
 
     return nfa;
 }
@@ -677,6 +755,38 @@ bytecode_ptr<NFA> sheng32Compile(raw_dfa &raw, const CompileContext &cc,
 
     return shengCompile_int<sheng32>(raw, cc, accel_states, strat, info);
 }
+
+bytecode_ptr<NFA> sheng64Compile(raw_dfa &raw, const CompileContext &cc,
+                                 const ReportManager &rm, bool only_accel_init,
+                                 set<dstate_id_t> *accel_states) {
+    if (!cc.grey.allowSheng) {
+        DEBUG_PRINTF("Sheng is not allowed!\n");
+        return nullptr;
+    }
+
+    sheng_build_strat strat(raw, rm, only_accel_init);
+    dfa_info info(strat);
+
+    DEBUG_PRINTF("Trying to compile a %zu state Sheng\n", raw.states.size());
+
+    DEBUG_PRINTF("Anchored start state id: %u, floating start state id: %u\n",
+                 raw.start_anchored, raw.start_floating);
+
+    DEBUG_PRINTF("This DFA %s die so effective number of states is %zu\n",
+                 info.can_die ? "can" : "cannot", info.size());
+    assert(info.size() > 32);
+    if (info.size() > 64) {
+        DEBUG_PRINTF("Too many states\n");
+        return nullptr;
+    }
+    vector<dstate> old_states;
+    old_states = info.states;
+    auto nfa = shengCompile_int<sheng64>(raw, cc, accel_states, strat, info);
+    if (!nfa) {
+        info.states = old_states;
+    }
+    return nfa;
+}
 #endif
 
 } // namespace ue2
index b36e27beedb5f0f2b0fd7fe2f1cbcee17ccc614e..96688eef60c57b37a516c35144667141061ccaaa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, Intel Corporation
+ * Copyright (c) 2016-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -75,6 +75,10 @@ bytecode_ptr<NFA> shengCompile(raw_dfa &raw, const CompileContext &cc,
 bytecode_ptr<NFA> sheng32Compile(raw_dfa &raw, const CompileContext &cc,
                                  const ReportManager &rm, bool only_accel_init,
                                  std::set<dstate_id_t> *accel_states = nullptr);
+
+bytecode_ptr<NFA> sheng64Compile(raw_dfa &raw, const CompileContext &cc,
+                                 const ReportManager &rm, bool only_accel_init,
+                                 std::set<dstate_id_t> *accel_states = nullptr);
 #endif
 
 struct sheng_escape_info {
index d6cca401a415f934de22671ea96222b3371a2a11..e1e7fc9d73ea285574ec9d4e42ea7906bfcb805b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, Intel Corporation
+ * Copyright (c) 2016-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -79,6 +79,21 @@ const sstate_aux *get_aux32(const NFA *n, dstate_id_t i) {
 
     return aux;
 }
+
+static
+const sstate_aux *get_aux64(const NFA *n, dstate_id_t i) {
+    assert(n && isSheng64Type(n->type));
+
+    const sheng64 *s = (const sheng64 *)getImplNfa(n);
+    const sstate_aux *aux_base =
+        (const sstate_aux *)((const char *)n + s->aux_offset);
+
+    const sstate_aux *aux = aux_base + i;
+
+    assert((const char *)aux < (const char *)s + s->length);
+
+    return aux;
+}
 #endif
 
 static
@@ -111,6 +126,21 @@ void dumpHeader32(FILE *f, const sheng32 *s) {
             !!(s->flags & SHENG_FLAG_CAN_DIE),
             !!(s->flags & SHENG_FLAG_SINGLE_REPORT));
 }
+
+static
+void dumpHeader64(FILE *f, const sheng64 *s) {
+    fprintf(f, "number of states: %u, DFA engine size: %u\n", s->n_states,
+            s->length);
+    fprintf(f, "aux base offset: %u, reports base offset: %u, "
+               "accel offset: %u\n",
+            s->aux_offset, s->report_offset, s->accel_offset);
+    fprintf(f, "anchored start state: %u, floating start state: %u\n",
+            s->anchored & SHENG64_STATE_MASK, s->floating & SHENG64_STATE_MASK);
+    fprintf(f, "has accel: %u can die: %u single report: %u\n",
+            !!(s->flags & SHENG_FLAG_HAS_ACCEL),
+            !!(s->flags & SHENG_FLAG_CAN_DIE),
+            !!(s->flags & SHENG_FLAG_SINGLE_REPORT));
+}
 #endif
 
 static
@@ -129,6 +159,14 @@ void dumpAux32(FILE *f, u32 state, const sstate_aux *aux) {
             state, aux->accept, aux->accept_eod, aux->accel,
             aux->top & SHENG32_STATE_MASK);
 }
+
+static
+void dumpAux64(FILE *f, u32 state, const sstate_aux *aux) {
+    fprintf(f, "state id: %u, reports offset: %u, EOD reports offset: %u, "
+               "accel offset: %u, top: %u\n",
+            state, aux->accept, aux->accept_eod, aux->accel,
+            aux->top & SHENG64_STATE_MASK);
+}
 #endif
 
 static
@@ -162,8 +200,6 @@ void dumpMasks(FILE *f, const sheng *s) {
 #if defined(HAVE_AVX512VBMI)
 static
 void dumpMasks32(FILE *f, const sheng32 *s) {
-    //u8 flags[64];
-    //memcpy(flags, &s->flag_mask, sizeof(m512));
     for (u32 chr = 0; chr < 256; chr++) {
         u8 buf[64];
         m512 succ_mask = s->succ_masks[chr];
@@ -181,6 +217,26 @@ void dumpMasks32(FILE *f, const sheng32 *s) {
         fprintf(f, "\n");
     }
 }
+
+static
+void dumpMasks64(FILE *f, const sheng64 *s) {
+    for (u32 chr = 0; chr < 256; chr++) {
+        u8 buf[64];
+        m512 succ_mask = s->succ_masks[chr];
+        memcpy(buf, &succ_mask, sizeof(m512));
+
+        fprintf(f, "%3u: ", chr);
+        for (u32 pos = 0; pos < 64; pos++) {
+            u8 c = buf[pos];
+            if (c & SHENG64_STATE_FLAG_MASK) {
+                fprintf(f, "%2u* ", c & SHENG64_STATE_MASK);
+            } else {
+                fprintf(f, "%2u  ", c & SHENG64_STATE_MASK);
+            }
+        }
+        fprintf(f, "\n");
+    }
+}
 #endif
 
 static
@@ -259,6 +315,44 @@ void nfaExecSheng32_dumpText(const NFA *nfa, FILE *f) {
 
     fprintf(f, "\n");
 }
+
+static
+void nfaExecSheng64_dumpText(const NFA *nfa, FILE *f) {
+    assert(nfa->type == SHENG_NFA_64);
+    const sheng64 *s = (const sheng64 *)getImplNfa(nfa);
+
+    fprintf(f, "sheng64 DFA\n");
+    dumpHeader64(f, s);
+
+    for (u32 state = 0; state < s->n_states; state++) {
+        const sstate_aux *aux = get_aux64(nfa, state);
+        dumpAux64(f, state, aux);
+        if (aux->accept) {
+            fprintf(f, "report list:\n");
+            const report_list *rl =
+                (const report_list *)((const char *)nfa + aux->accept);
+            dumpReports(f, rl);
+        }
+        if (aux->accept_eod) {
+            fprintf(f, "EOD report list:\n");
+            const report_list *rl =
+                (const report_list *)((const char *)nfa + aux->accept_eod);
+            dumpReports(f, rl);
+        }
+        if (aux->accel) {
+            fprintf(f, "accel:\n");
+            const AccelAux *accel =
+                (const AccelAux *)((const char *)nfa + aux->accel);
+            dumpAccelInfo(f, *accel);
+        }
+    }
+
+    fprintf(f, "\n");
+
+    dumpMasks64(f, s);
+
+    fprintf(f, "\n");
+}
 #endif
 
 static
@@ -336,6 +430,36 @@ void describeNode<sheng32>(const NFA *n, const sheng32 *s, u16 i, FILE *f) {
         fprintf(f, "STARTF -> %u [color = red ]\n", i);
     }
 }
+
+template <>
+void describeNode<sheng64>(const NFA *n, const sheng64 *s, u16 i, FILE *f) {
+    const sstate_aux *aux = get_aux64(n, i);
+
+    fprintf(f, "%u [ width = 1, fixedsize = true, fontsize = 12, "
+               "label = \"%u\" ]; \n",
+            i, i);
+
+    if (aux->accept_eod) {
+        fprintf(f, "%u [ color = darkorchid ];\n", i);
+    }
+
+    if (aux->accept) {
+        fprintf(f, "%u [ shape = doublecircle ];\n", i);
+    }
+
+    if (aux->top && (aux->top & SHENG64_STATE_MASK) != i) {
+        fprintf(f, "%u -> %u [color = darkgoldenrod weight=0.1 ]\n", i,
+                aux->top & SHENG64_STATE_MASK);
+    }
+
+    if (i == (s->anchored & SHENG64_STATE_MASK)) {
+        fprintf(f, "STARTA -> %u [color = blue ]\n", i);
+    }
+
+    if (i == (s->floating & SHENG64_STATE_MASK)) {
+        fprintf(f, "STARTF -> %u [color = red ]\n", i);
+    }
+}
 #endif
 
 static
@@ -407,6 +531,24 @@ void sheng32GetTransitions(const NFA *n, u16 state, u16 *t) {
 
     t[TOP] = aux->top & SHENG32_STATE_MASK;
 }
+
+static
+void sheng64GetTransitions(const NFA *n, u16 state, u16 *t) {
+    assert(isSheng64Type(n->type));
+    const sheng64 *s = (const sheng64 *)getImplNfa(n);
+    const sstate_aux *aux = get_aux64(n, state);
+
+    for (unsigned i = 0; i < N_CHARS; i++) {
+        u8 buf[64];
+        m512 succ_mask = s->succ_masks[i];
+
+        memcpy(buf, &succ_mask, sizeof(m512));
+
+        t[i] = buf[state] & SHENG64_STATE_MASK;
+    }
+
+    t[TOP] = aux->top & SHENG64_STATE_MASK;
+}
 #endif
 
 static
@@ -449,6 +591,26 @@ void nfaExecSheng32_dumpDot(const NFA *nfa, FILE *f) {
 
     fprintf(f, "}\n");
 }
+
+static
+void nfaExecSheng64_dumpDot(const NFA *nfa, FILE *f) {
+    assert(nfa->type == SHENG_NFA_64);
+    const sheng64 *s = (const sheng64 *)getImplNfa(nfa);
+
+    dumpDotPreambleDfa(f);
+
+    for (u16 i = 1; i < s->n_states; i++) {
+        describeNode<sheng64>(nfa, s, i, f);
+
+        u16 t[ALPHABET_SIZE];
+
+        sheng64GetTransitions(nfa, i, t);
+
+        describeEdge(f, t, i);
+    }
+
+    fprintf(f, "}\n");
+}
 #endif
 
 void nfaExecSheng_dump(const NFA *nfa, const string &base) {
@@ -465,4 +627,12 @@ void nfaExecSheng32_dump(UNUSED const NFA *nfa, UNUSED const string &base) {
 #endif
 }
 
+void nfaExecSheng64_dump(UNUSED const NFA *nfa, UNUSED const string &base) {
+#if defined(HAVE_AVX512VBMI)
+    assert(nfa->type == SHENG_NFA_64);
+    nfaExecSheng64_dumpText(nfa, StdioFile(base + ".txt", "w"));
+    nfaExecSheng64_dumpDot(nfa, StdioFile(base + ".dot", "w"));
+#endif
+}
+
 } // namespace ue2
index a9a762331d351790698282cda1be16eaeacc6d2c..3215367428f43172c7029dd4d1c7007525522c65 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Intel Corporation
+ * Copyright (c) 2016-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -39,6 +39,7 @@ namespace ue2 {
 
 void nfaExecSheng_dump(const struct NFA *nfa, const std::string &base);
 void nfaExecSheng32_dump(const struct NFA *nfa, const std::string &base);
+void nfaExecSheng64_dump(const struct NFA *nfa, const std::string &base);
 
 } // namespace ue2
 
index 8e1d7095bdd13fb962dddcae136936670adcd02a..abd5281d7c077fcc85c275befb4e6c6f7d188845 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, Intel Corporation
+ * Copyright (c) 2015-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -636,6 +636,9 @@ bytecode_ptr<NFA> getDfa(raw_dfa &rdfa, bool is_transient,
     if (!dfa) {
         dfa = sheng32Compile(rdfa, cc, rm, false);
     }
+    if (!dfa) {
+        dfa = sheng64Compile(rdfa, cc, rm, false);
+    }
 #endif
     if (!dfa) {
         // Sheng wasn't successful, so unleash McClellan!
index 909fdcb3b07a210cdac3f8c987e2b46c61366588..63a79aa0de6e72474c7f523c8f7ba67a9178d6c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, Intel Corporation
+ * Copyright (c) 2015-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -797,6 +797,9 @@ bytecode_ptr<NFA> getDfa(raw_dfa &rdfa, const CompileContext &cc,
         if (!dfa) {
             dfa = sheng32Compile(rdfa, cc, rm, only_accel_init, &accel_states);
         }
+        if (!dfa) {
+            dfa = sheng64Compile(rdfa, cc, rm, only_accel_init, &accel_states);
+        }
 #endif
     }
     if (!dfa) {