1 /*
2  * Copyright (c) 2015-2020, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  * Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *  * Neither the name of Intel Corporation nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "nfa_build_util.h"
30 
31 #include "limex_internal.h"
32 #include "mcclellancompile.h"
33 #include "mcsheng_compile.h"
34 #include "shengcompile.h"
35 #include "nfa_internal.h"
36 #include "repeat_internal.h"
37 #include "ue2common.h"
38 
39 #include <algorithm>
40 #include <cassert>
41 #include <cstddef>
42 #include <cstdio>
43 #include <cstdlib>
44 #include <cstring>
45 #include <sstream>
46 
47 using namespace std;
48 
49 namespace ue2 {
50 
51 namespace {
52 
53 template<NFAEngineType t> struct NFATraits { };
54 
55 template<template<NFAEngineType t> class sfunc, typename rv_t, typename arg_t,
56          NFAEngineType lb>
57 struct DISPATCH_BY_NFA_TYPE_INT {
doOpue2::__anon648aa2300111::DISPATCH_BY_NFA_TYPE_INT58     static rv_t doOp(NFAEngineType i, const arg_t &arg) {
59         if (i == lb) {
60             return sfunc<lb>::call(arg);
61         } else {
62             return DISPATCH_BY_NFA_TYPE_INT<sfunc, rv_t, arg_t,
63                                             (NFAEngineType)(lb + 1)>
64                      ::doOp(i, arg);
65         }
66     }
67 };
68 
69 template<template<NFAEngineType t> class sfunc, typename rv_t, typename arg_t>
70 struct DISPATCH_BY_NFA_TYPE_INT<sfunc, rv_t, arg_t, INVALID_NFA> {
71     // dummy
doOpue2::__anon648aa2300111::DISPATCH_BY_NFA_TYPE_INT72     static rv_t doOp(NFAEngineType, const arg_t &) {
73         assert(0);
74         throw std::logic_error("Unreachable");
75     }
76 };
77 
78 #define DISPATCH_BY_NFA_TYPE(i, op, arg)                                       \
79     DISPATCH_BY_NFA_TYPE_INT<op, decltype(op<(NFAEngineType)0>::call(arg)),    \
80                              decltype(arg), (NFAEngineType)0>::doOp(i, arg)
81 }
82 
83 typedef bool (*nfa_dispatch_fn)(const NFA *nfa);
84 
85 template<typename T>
86 static
has_accel_limex(const NFA * nfa)87 bool has_accel_limex(const NFA *nfa) {
88     const T *limex = (const T *)getImplNfa(nfa);
89     return limex->accelCount;
90 }
91 
92 template<typename T>
93 static
has_repeats_limex(const NFA * nfa)94 bool has_repeats_limex(const NFA *nfa) {
95     const T *limex = (const T *)getImplNfa(nfa);
96     return limex->repeatCount;
97 }
98 
99 
100 template<typename T>
101 static
has_repeats_other_than_firsts_limex(const NFA * nfa)102 bool has_repeats_other_than_firsts_limex(const NFA *nfa) {
103     const T *limex = (const T *)getImplNfa(nfa);
104     const char *ptr = (const char *)limex;
105 
106     const u32 *repeatOffset = (const u32 *)(ptr + limex->repeatOffset);
107 
108     for (u32 i = 0; i < limex->repeatCount; i++) {
109         u32 offset = repeatOffset[i];
110         const NFARepeatInfo *info = (const NFARepeatInfo *)(ptr + offset);
111         const RepeatInfo *repeat =
112             (const RepeatInfo *)((const char *)info + sizeof(*info));
113         if (repeat->type != REPEAT_FIRST) {
114             return true;
115         }
116     }
117 
118     return false;
119 }
120 
121 static
dispatch_false(const NFA *)122 bool dispatch_false(const NFA *) {
123     return false;
124 }
125 
126 #ifdef DUMP_SUPPORT
127 namespace {
128 template<NFAEngineType t>
129 struct getName {
callue2::__anon648aa2300211::getName130     static const char *call(void *) {
131         return NFATraits<t>::name;
132     }
133 };
134 
135 // descr helper for LimEx NFAs
136 template<NFAEngineType t>
137 static
getDescriptionLimEx(const NFA * nfa)138 string getDescriptionLimEx(const NFA *nfa) {
139     const typename NFATraits<t>::implNFA_t *limex =
140         (const typename NFATraits<t>::implNFA_t *)getImplNfa(nfa);
141     ostringstream oss;
142     oss << NFATraits<t>::name << "/" << limex->exceptionCount;
143     if (limex->repeatCount) {
144         oss << " +" << limex->repeatCount << "r";
145     }
146     return oss.str();
147 }
148 }
149 
150 // generic description: just return the name
151 namespace {
152 template<NFAEngineType t>
153 struct getDescription {
callue2::__anon648aa2300311::getDescription154     static string call(const void *) {
155         return string(NFATraits<t>::name);
156     }
157 };
158 }
159 #endif
160 
161 
162 /* build-utility Traits */
163 
164 namespace {
165 enum NFACategory {NFA_LIMEX, NFA_OTHER};
166 
167 // Some of our traits we want around in DUMP_SUPPORT mode only.
168 #if defined(DUMP_SUPPORT)
169 #define DO_IF_DUMP_SUPPORT(a) a
170 #else
171 #define DO_IF_DUMP_SUPPORT(a)
172 #endif
173 
174 #define MAKE_LIMEX_TRAITS(mlt_size, mlt_align)                          \
175     template<> struct NFATraits<LIMEX_NFA_##mlt_size> {                 \
176         static UNUSED const char *name;                                 \
177         static const NFACategory category = NFA_LIMEX;                  \
178         typedef LimExNFA##mlt_size implNFA_t;                           \
179         static const nfa_dispatch_fn has_accel;                         \
180         static const nfa_dispatch_fn has_repeats;                       \
181         static const nfa_dispatch_fn has_repeats_other_than_firsts;     \
182         static const u32 stateAlign =                                   \
183                 MAX(mlt_align, alignof(RepeatControl));                 \
184     };                                                                  \
185     const nfa_dispatch_fn NFATraits<LIMEX_NFA_##mlt_size>::has_accel    \
186             = has_accel_limex<LimExNFA##mlt_size>;                      \
187     const nfa_dispatch_fn NFATraits<LIMEX_NFA_##mlt_size>::has_repeats  \
188             = has_repeats_limex<LimExNFA##mlt_size>;                    \
189     const nfa_dispatch_fn                                               \
190         NFATraits<LIMEX_NFA_##mlt_size>::has_repeats_other_than_firsts  \
191             = has_repeats_other_than_firsts_limex<LimExNFA##mlt_size>;  \
192     DO_IF_DUMP_SUPPORT(                                                 \
193     const char *NFATraits<LIMEX_NFA_##mlt_size>::name                   \
194         = "LimEx "#mlt_size;                                            \
195     template<> struct getDescription<LIMEX_NFA_##mlt_size> {            \
196         static string call(const void *p) {                             \
197             return getDescriptionLimEx<LIMEX_NFA_##mlt_size>((const NFA *)p); \
198         }                                                               \
199     };)
200 
201 MAKE_LIMEX_TRAITS(32,  alignof(u32))
202 MAKE_LIMEX_TRAITS(64,  alignof(m128)) /* special, 32bit arch uses m128 */
203 MAKE_LIMEX_TRAITS(128, alignof(m128))
204 MAKE_LIMEX_TRAITS(256, alignof(m256))
205 MAKE_LIMEX_TRAITS(384, alignof(m384))
206 MAKE_LIMEX_TRAITS(512, alignof(m512))
207 
208 template<> struct NFATraits<MCCLELLAN_NFA_8> {
209     UNUSED static const char *name;
210     static const NFACategory category = NFA_OTHER;
211     static const u32 stateAlign = 1;
212     static const nfa_dispatch_fn has_accel;
213     static const nfa_dispatch_fn has_repeats;
214     static const nfa_dispatch_fn has_repeats_other_than_firsts;
215 };
216 const nfa_dispatch_fn NFATraits<MCCLELLAN_NFA_8>::has_accel = has_accel_mcclellan;
217 const nfa_dispatch_fn NFATraits<MCCLELLAN_NFA_8>::has_repeats = dispatch_false;
218 const nfa_dispatch_fn NFATraits<MCCLELLAN_NFA_8>::has_repeats_other_than_firsts = dispatch_false;
219 #if defined(DUMP_SUPPORT)
220 const char *NFATraits<MCCLELLAN_NFA_8>::name = "McClellan 8";
221 #endif
222 
223 template<> struct NFATraits<MCCLELLAN_NFA_16> {
224     UNUSED static const char *name;
225     static const NFACategory category = NFA_OTHER;
226     static const u32 stateAlign = 2;
227     static const nfa_dispatch_fn has_accel;
228     static const nfa_dispatch_fn has_repeats;
229     static const nfa_dispatch_fn has_repeats_other_than_firsts;
230 };
231 const nfa_dispatch_fn NFATraits<MCCLELLAN_NFA_16>::has_accel = has_accel_mcclellan;
232 const nfa_dispatch_fn NFATraits<MCCLELLAN_NFA_16>::has_repeats = dispatch_false;
233 const nfa_dispatch_fn NFATraits<MCCLELLAN_NFA_16>::has_repeats_other_than_firsts = dispatch_false;
234 #if defined(DUMP_SUPPORT)
235 const char *NFATraits<MCCLELLAN_NFA_16>::name = "McClellan 16";
236 #endif
237 
238 template<> struct NFATraits<GOUGH_NFA_8> {
239     UNUSED static const char *name;
240     static const NFACategory category = NFA_OTHER;
241     static const u32 stateAlign = 8;
242     static const nfa_dispatch_fn has_accel;
243     static const nfa_dispatch_fn has_repeats;
244     static const nfa_dispatch_fn has_repeats_other_than_firsts;
245 };
246 const nfa_dispatch_fn NFATraits<GOUGH_NFA_8>::has_accel = has_accel_mcclellan;
247 const nfa_dispatch_fn NFATraits<GOUGH_NFA_8>::has_repeats = dispatch_false;
248 const nfa_dispatch_fn NFATraits<GOUGH_NFA_8>::has_repeats_other_than_firsts = dispatch_false;
249 #if defined(DUMP_SUPPORT)
250 const char *NFATraits<GOUGH_NFA_8>::name = "Goughfish 8";
251 #endif
252 
253 template<> struct NFATraits<GOUGH_NFA_16> {
254     UNUSED static const char *name;
255     static const NFACategory category = NFA_OTHER;
256     static const u32 stateAlign = 8;
257     static const nfa_dispatch_fn has_accel;
258     static const nfa_dispatch_fn has_repeats;
259     static const nfa_dispatch_fn has_repeats_other_than_firsts;
260 };
261 const nfa_dispatch_fn NFATraits<GOUGH_NFA_16>::has_accel = has_accel_mcclellan;
262 const nfa_dispatch_fn NFATraits<GOUGH_NFA_16>::has_repeats = dispatch_false;
263 const nfa_dispatch_fn NFATraits<GOUGH_NFA_16>::has_repeats_other_than_firsts = dispatch_false;
264 #if defined(DUMP_SUPPORT)
265 const char *NFATraits<GOUGH_NFA_16>::name = "Goughfish 16";
266 #endif
267 
268 template<> struct NFATraits<MPV_NFA> {
269     UNUSED static const char *name;
270     static const NFACategory category = NFA_OTHER;
271     static const u32 stateAlign = 8;
272     static const nfa_dispatch_fn has_accel;
273     static const nfa_dispatch_fn has_repeats;
274     static const nfa_dispatch_fn has_repeats_other_than_firsts;
275 };
276 const nfa_dispatch_fn NFATraits<MPV_NFA>::has_accel = dispatch_false;
277 const nfa_dispatch_fn NFATraits<MPV_NFA>::has_repeats = dispatch_false;
278 const nfa_dispatch_fn NFATraits<MPV_NFA>::has_repeats_other_than_firsts = dispatch_false;
279 #if defined(DUMP_SUPPORT)
280 const char *NFATraits<MPV_NFA>::name = "Mega-Puff-Vac";
281 #endif
282 
283 template<> struct NFATraits<CASTLE_NFA> {
284     UNUSED static const char *name;
285     static const NFACategory category = NFA_OTHER;
286     static const u32 stateAlign = 8;
287     static const nfa_dispatch_fn has_accel;
288     static const nfa_dispatch_fn has_repeats;
289     static const nfa_dispatch_fn has_repeats_other_than_firsts;
290 };
291 const nfa_dispatch_fn NFATraits<CASTLE_NFA>::has_accel = dispatch_false;
292 const nfa_dispatch_fn NFATraits<CASTLE_NFA>::has_repeats = dispatch_false;
293 const nfa_dispatch_fn NFATraits<CASTLE_NFA>::has_repeats_other_than_firsts = dispatch_false;
294 #if defined(DUMP_SUPPORT)
295 const char *NFATraits<CASTLE_NFA>::name = "Castle";
296 #endif
297 
298 template<> struct NFATraits<LBR_NFA_DOT> {
299     UNUSED static const char *name;
300     static const NFACategory category = NFA_OTHER;
301     static const u32 stateAlign = 8;
302     static const nfa_dispatch_fn has_accel;
303     static const nfa_dispatch_fn has_repeats;
304     static const nfa_dispatch_fn has_repeats_other_than_firsts;
305 };
306 const nfa_dispatch_fn NFATraits<LBR_NFA_DOT>::has_accel = dispatch_false;
307 const nfa_dispatch_fn NFATraits<LBR_NFA_DOT>::has_repeats = dispatch_false;
308 const nfa_dispatch_fn NFATraits<LBR_NFA_DOT>::has_repeats_other_than_firsts = dispatch_false;
309 #if defined(DUMP_SUPPORT)
310 const char *NFATraits<LBR_NFA_DOT>::name = "Lim Bounded Repeat (D)";
311 #endif
312 
313 template<> struct NFATraits<LBR_NFA_VERM> {
314     UNUSED static const char *name;
315     static const NFACategory category = NFA_OTHER;
316     static const u32 stateAlign = 8;
317     static const nfa_dispatch_fn has_accel;
318     static const nfa_dispatch_fn has_repeats;
319     static const nfa_dispatch_fn has_repeats_other_than_firsts;
320 };
321 const nfa_dispatch_fn NFATraits<LBR_NFA_VERM>::has_accel = dispatch_false;
322 const nfa_dispatch_fn NFATraits<LBR_NFA_VERM>::has_repeats = dispatch_false;
323 const nfa_dispatch_fn NFATraits<LBR_NFA_VERM>::has_repeats_other_than_firsts = dispatch_false;
324 #if defined(DUMP_SUPPORT)
325 const char *NFATraits<LBR_NFA_VERM>::name = "Lim Bounded Repeat (V)";
326 #endif
327 
328 template<> struct NFATraits<LBR_NFA_NVERM> {
329     UNUSED static const char *name;
330     static const NFACategory category = NFA_OTHER;
331     static const u32 stateAlign = 8;
332     static const nfa_dispatch_fn has_accel;
333     static const nfa_dispatch_fn has_repeats;
334     static const nfa_dispatch_fn has_repeats_other_than_firsts;
335 };
336 const nfa_dispatch_fn NFATraits<LBR_NFA_NVERM>::has_accel = dispatch_false;
337 const nfa_dispatch_fn NFATraits<LBR_NFA_NVERM>::has_repeats = dispatch_false;
338 const nfa_dispatch_fn NFATraits<LBR_NFA_NVERM>::has_repeats_other_than_firsts = dispatch_false;
339 #if defined(DUMP_SUPPORT)
340 const char *NFATraits<LBR_NFA_NVERM>::name = "Lim Bounded Repeat (NV)";
341 #endif
342 
343 template<> struct NFATraits<LBR_NFA_SHUF> {
344     UNUSED static const char *name;
345     static const NFACategory category = NFA_OTHER;
346     static const u32 stateAlign = 8;
347     static const nfa_dispatch_fn has_accel;
348     static const nfa_dispatch_fn has_repeats;
349     static const nfa_dispatch_fn has_repeats_other_than_firsts;
350 };
351 const nfa_dispatch_fn NFATraits<LBR_NFA_SHUF>::has_accel = dispatch_false;
352 const nfa_dispatch_fn NFATraits<LBR_NFA_SHUF>::has_repeats = dispatch_false;
353 const nfa_dispatch_fn NFATraits<LBR_NFA_SHUF>::has_repeats_other_than_firsts = dispatch_false;
354 #if defined(DUMP_SUPPORT)
355 const char *NFATraits<LBR_NFA_SHUF>::name = "Lim Bounded Repeat (S)";
356 #endif
357 
358 template<> struct NFATraits<LBR_NFA_TRUF> {
359     UNUSED static const char *name;
360     static const NFACategory category = NFA_OTHER;
361     static const u32 stateAlign = 8;
362     static const nfa_dispatch_fn has_accel;
363     static const nfa_dispatch_fn has_repeats;
364     static const nfa_dispatch_fn has_repeats_other_than_firsts;
365 };
366 const nfa_dispatch_fn NFATraits<LBR_NFA_TRUF>::has_accel = dispatch_false;
367 const nfa_dispatch_fn NFATraits<LBR_NFA_TRUF>::has_repeats = dispatch_false;
368 const nfa_dispatch_fn NFATraits<LBR_NFA_TRUF>::has_repeats_other_than_firsts = dispatch_false;
369 #if defined(DUMP_SUPPORT)
370 const char *NFATraits<LBR_NFA_TRUF>::name = "Lim Bounded Repeat (M)";
371 #endif
372 
373 template<> struct NFATraits<SHENG_NFA> {
374     UNUSED static const char *name;
375     static const NFACategory category = NFA_OTHER;
376     static const u32 stateAlign = 1;
377     static const nfa_dispatch_fn has_accel;
378     static const nfa_dispatch_fn has_repeats;
379     static const nfa_dispatch_fn has_repeats_other_than_firsts;
380 };
381 const nfa_dispatch_fn NFATraits<SHENG_NFA>::has_accel = has_accel_sheng;
382 const nfa_dispatch_fn NFATraits<SHENG_NFA>::has_repeats = dispatch_false;
383 const nfa_dispatch_fn NFATraits<SHENG_NFA>::has_repeats_other_than_firsts = dispatch_false;
384 #if defined(DUMP_SUPPORT)
385 const char *NFATraits<SHENG_NFA>::name = "Sheng";
386 #endif
387 
388 template<> struct NFATraits<TAMARAMA_NFA> {
389     UNUSED static const char *name;
390     static const NFACategory category = NFA_OTHER;
391     static const u32 stateAlign = 64;
392     static const nfa_dispatch_fn has_accel;
393     static const nfa_dispatch_fn has_repeats;
394     static const nfa_dispatch_fn has_repeats_other_than_firsts;
395 };
396 const nfa_dispatch_fn NFATraits<TAMARAMA_NFA>::has_accel = dispatch_false;
397 const nfa_dispatch_fn NFATraits<TAMARAMA_NFA>::has_repeats = dispatch_false;
398 const nfa_dispatch_fn NFATraits<TAMARAMA_NFA>::has_repeats_other_than_firsts = dispatch_false;
399 #if defined(DUMP_SUPPORT)
400 const char *NFATraits<TAMARAMA_NFA>::name = "Tamarama";
401 #endif
402 
403 template<> struct NFATraits<MCSHENG_NFA_8> {
404     UNUSED static const char *name;
405     static const NFACategory category = NFA_OTHER;
406     static const u32 stateAlign = 1;
407     static const nfa_dispatch_fn has_accel;
408     static const nfa_dispatch_fn has_repeats;
409     static const nfa_dispatch_fn has_repeats_other_than_firsts;
410 };
411 const nfa_dispatch_fn NFATraits<MCSHENG_NFA_8>::has_accel = has_accel_mcsheng;
412 const nfa_dispatch_fn NFATraits<MCSHENG_NFA_8>::has_repeats = dispatch_false;
413 const nfa_dispatch_fn NFATraits<MCSHENG_NFA_8>::has_repeats_other_than_firsts = dispatch_false;
414 #if defined(DUMP_SUPPORT)
415 const char *NFATraits<MCSHENG_NFA_8>::name = "Shengy McShengFace 8";
416 #endif
417 
418 template<> struct NFATraits<MCSHENG_NFA_16> {
419     UNUSED static const char *name;
420     static const NFACategory category = NFA_OTHER;
421     static const u32 stateAlign = 2;
422     static const nfa_dispatch_fn has_accel;
423     static const nfa_dispatch_fn has_repeats;
424     static const nfa_dispatch_fn has_repeats_other_than_firsts;
425 };
426 const nfa_dispatch_fn NFATraits<MCSHENG_NFA_16>::has_accel = has_accel_mcsheng;
427 const nfa_dispatch_fn NFATraits<MCSHENG_NFA_16>::has_repeats = dispatch_false;
428 const nfa_dispatch_fn NFATraits<MCSHENG_NFA_16>::has_repeats_other_than_firsts = dispatch_false;
429 #if defined(DUMP_SUPPORT)
430 const char *NFATraits<MCSHENG_NFA_16>::name = "Shengy McShengFace 16";
431 #endif
432 
433 template<> struct NFATraits<SHENG_NFA_32> {
434     UNUSED static const char *name;
435     static const NFACategory category = NFA_OTHER;
436     static const u32 stateAlign = 1;
437     static const nfa_dispatch_fn has_accel;
438     static const nfa_dispatch_fn has_repeats;
439     static const nfa_dispatch_fn has_repeats_other_than_firsts;
440 };
441 const nfa_dispatch_fn NFATraits<SHENG_NFA_32>::has_accel = has_accel_sheng;
442 const nfa_dispatch_fn NFATraits<SHENG_NFA_32>::has_repeats = dispatch_false;
443 const nfa_dispatch_fn NFATraits<SHENG_NFA_32>::has_repeats_other_than_firsts = dispatch_false;
444 #if defined(DUMP_SUPPORT)
445 const char *NFATraits<SHENG_NFA_32>::name = "Sheng 32";
446 #endif
447 
448 template<> struct NFATraits<SHENG_NFA_64> {
449     UNUSED static const char *name;
450     static const NFACategory category = NFA_OTHER;
451     static const u32 stateAlign = 1;
452     static const nfa_dispatch_fn has_accel;
453     static const nfa_dispatch_fn has_repeats;
454     static const nfa_dispatch_fn has_repeats_other_than_firsts;
455 };
456 const nfa_dispatch_fn NFATraits<SHENG_NFA_64>::has_accel = has_accel_sheng;
457 const nfa_dispatch_fn NFATraits<SHENG_NFA_64>::has_repeats = dispatch_false;
458 const nfa_dispatch_fn NFATraits<SHENG_NFA_64>::has_repeats_other_than_firsts = dispatch_false;
459 #if defined(DUMP_SUPPORT)
460 const char *NFATraits<SHENG_NFA_64>::name = "Sheng 64";
461 #endif
462 
463 template<> struct NFATraits<MCSHENG_64_NFA_8> {
464     UNUSED static const char *name;
465     static const NFACategory category = NFA_OTHER;
466     static const u32 stateAlign = 1;
467     static const nfa_dispatch_fn has_accel;
468     static const nfa_dispatch_fn has_repeats;
469     static const nfa_dispatch_fn has_repeats_other_than_firsts;
470 };
471 const nfa_dispatch_fn NFATraits<MCSHENG_64_NFA_8>::has_accel = has_accel_mcsheng;
472 const nfa_dispatch_fn NFATraits<MCSHENG_64_NFA_8>::has_repeats = dispatch_false;
473 const nfa_dispatch_fn NFATraits<MCSHENG_64_NFA_8>::has_repeats_other_than_firsts = dispatch_false;
474 #if defined(DUMP_SUPPORT)
475 const char *NFATraits<MCSHENG_64_NFA_8>::name = "Shengy64 McShengFace 8";
476 #endif
477 
478 template<> struct NFATraits<MCSHENG_64_NFA_16> {
479     UNUSED static const char *name;
480     static const NFACategory category = NFA_OTHER;
481     static const u32 stateAlign = 2;
482     static const nfa_dispatch_fn has_accel;
483     static const nfa_dispatch_fn has_repeats;
484     static const nfa_dispatch_fn has_repeats_other_than_firsts;
485 };
486 const nfa_dispatch_fn NFATraits<MCSHENG_64_NFA_16>::has_accel = has_accel_mcsheng;
487 const nfa_dispatch_fn NFATraits<MCSHENG_64_NFA_16>::has_repeats = dispatch_false;
488 const nfa_dispatch_fn NFATraits<MCSHENG_64_NFA_16>::has_repeats_other_than_firsts = dispatch_false;
489 #if defined(DUMP_SUPPORT)
490 const char *NFATraits<MCSHENG_64_NFA_16>::name = "Shengy64 McShengFace 16";
491 #endif
492 } // namespace
493 
494 #if defined(DUMP_SUPPORT)
495 
nfa_type_name(NFAEngineType type)496 const char *nfa_type_name(NFAEngineType type) {
497     return DISPATCH_BY_NFA_TYPE(type, getName, nullptr);
498 }
499 
describe(const NFA & nfa)500 string describe(const NFA &nfa) {
501     return DISPATCH_BY_NFA_TYPE((NFAEngineType)nfa.type, getDescription, &nfa);
502 }
503 
504 #endif /* DUMP_SUPPORT */
505 
506 namespace {
507 template<NFAEngineType t>
508 struct getStateAlign {
callue2::__anon648aa2300511::getStateAlign509     static u32 call(void *) {
510         return NFATraits<t>::stateAlign;
511     }
512 };
513 }
514 
state_alignment(const NFA & nfa)515 u32 state_alignment(const NFA &nfa) {
516     return DISPATCH_BY_NFA_TYPE((NFAEngineType)nfa.type, getStateAlign, nullptr);
517 }
518 
519 namespace {
520 template<NFAEngineType t>
521 struct is_limex {
callue2::__anon648aa2300611::is_limex522     static bool call(const void *) {
523         return NFATraits<t>::category == NFA_LIMEX;
524     }
525 };
526 }
527 
528 namespace {
529 template<NFAEngineType t>
530 struct has_repeats_other_than_firsts_dispatch {
callue2::__anon648aa2300711::has_repeats_other_than_firsts_dispatch531     static nfa_dispatch_fn call(const void *) {
532         return NFATraits<t>::has_repeats_other_than_firsts;
533     }
534 };
535 }
536 
has_bounded_repeats_other_than_firsts(const NFA & nfa)537 bool has_bounded_repeats_other_than_firsts(const NFA &nfa) {
538     return DISPATCH_BY_NFA_TYPE((NFAEngineType)nfa.type,
539                                 has_repeats_other_than_firsts_dispatch,
540                                 &nfa)(&nfa);
541 }
542 
543 namespace {
544 template<NFAEngineType t>
545 struct has_repeats_dispatch {
callue2::__anon648aa2300811::has_repeats_dispatch546     static nfa_dispatch_fn call(const void *) {
547         return NFATraits<t>::has_repeats;
548     }
549 };
550 }
551 
has_bounded_repeats(const NFA & nfa)552 bool has_bounded_repeats(const NFA &nfa) {
553     return DISPATCH_BY_NFA_TYPE((NFAEngineType)nfa.type, has_repeats_dispatch,
554                                 &nfa)(&nfa);
555 }
556 
557 namespace {
558 template<NFAEngineType t>
559 struct has_accel_dispatch {
callue2::__anon648aa2300911::has_accel_dispatch560     static nfa_dispatch_fn call(const void *) {
561         return NFATraits<t>::has_accel;
562     }
563 };
564 }
565 
has_accel(const NFA & nfa)566 bool has_accel(const NFA &nfa) {
567     return DISPATCH_BY_NFA_TYPE((NFAEngineType)nfa.type, has_accel_dispatch,
568                                 &nfa)(&nfa);
569 }
570 
requires_decompress_key(const NFA & nfa)571 bool requires_decompress_key(const NFA &nfa) {
572     return DISPATCH_BY_NFA_TYPE((NFAEngineType)nfa.type, is_limex, &nfa);
573 }
574 
575 } // namespace ue2
576