1/*
2 * Copyright (c) 2015-2016, 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/** \file
30 \brief Limex Execution Engine Or:
31 How I Learned To Stop Worrying And Love The Preprocessor
32
33 This file includes utility functions which do not depend on the size of the
34 state or shift masks directly.
35*/
36
37#ifndef LIMEX_RUNTIME_H
38#define LIMEX_RUNTIME_H
39
40#include "limex_accel.h"
41#include "limex_context.h"
42#include "limex_internal.h"
43#include "nfa_api_util.h"
44#include "nfa_internal.h"
45#include "util/uniform_ops.h"
46
47////////////////////////////////////////////////////////////////////////////
48// LimEx NFA implementation code - common macros
49////////////////////////////////////////////////////////////////////////////
50
51#ifdef DEBUG_INPUT
52#include <ctype.h>
53#define DUMP_INPUT(index) DEBUG_PRINTF("input %p i=%zu: %02hhx (%c)\n", \
54 &input[index], index, input[index], \
55 isprint(input[index]) ? input[index] : ' ')
56#else
57#define DUMP_INPUT(index) do { } while(0)
58#endif
59
60#define NO_OUTPUT 0
61#define CALLBACK_OUTPUT 1
62#define FIRST_BYTE 16
63
64enum CacheResult {
65 DO_NOT_CACHE_RESULT,
66 CACHE_RESULT,
67 DO_NOT_CACHE_RESULT_AND_FLUSH_BR_ENTRIES
68};
69
70struct proto_cache {
71 char br;
72 const ReportID *reports;
73};
74
75#define PE_RV_HALT 1
76
77#ifdef STATE_ON_STACK
78#define pass_state s
79#else
80#define pass_state &s
81#endif
82
83#ifdef ESTATE_ON_STACK
84#define pass_estate estate
85#else
86#define pass_estate &estate
87#endif
88
89static really_inline
90int limexRunReports(const ReportID *reports, NfaCallback callback,
91 void *context, u64a offset) {
92 assert(reports);
93 assert(callback);
94
95 for (; *reports != MO_INVALID_IDX; ++reports) {
96 DEBUG_PRINTF("firing report for id %u at offset %llu\n",
97 *reports, offset);
98 int rv = callback(0, offset, *reports, context);
99 if (rv == MO_HALT_MATCHING) {
100 return MO_HALT_MATCHING;
101 }
102 }
103 return MO_CONTINUE_MATCHING; // continue
104}
105
106static really_inline
107int limexRunAccept(const char *limex_base, const struct NFAAccept *accept,
108 NfaCallback callback, void *context, u64a offset) {
109 if (accept->single_report) {
110 const ReportID report = accept->reports;
111 DEBUG_PRINTF("firing single report for id %u at offset %llu\n", report,
112 offset);
113 return callback(0, offset, report, context);
114 }
115 const ReportID *reports = (const ReportID *)(limex_base + accept->reports);
116 return limexRunReports(reports, callback, context, offset);
117}
118
119static really_inline
120int limexAcceptHasReport(const char *limex_base, const struct NFAAccept *accept,
121 ReportID report) {
122 if (accept->single_report) {
123 return accept->reports == report;
124 }
125
126 const ReportID *reports = (const ReportID *)(limex_base + accept->reports);
127 assert(*reports != MO_INVALID_IDX);
128 do {
129 if (*reports == report) {
130 return 1;
131 }
132 reports++;
133 } while (*reports != MO_INVALID_IDX);
134
135 return 0;
136}
137
138/** \brief Return a (correctly typed) pointer to the exception table. */
139#define getExceptionTable(exc_type, lim) \
140 ((const exc_type *)((const char *)(lim) + (lim)->exceptionOffset))
141
142/** \brief Return a pointer to the ordinary accepts table. */
143#define getAcceptTable(lim) \
144 ((const struct NFAAccept *)((const char *)(lim) + (lim)->acceptOffset))
145
146/** \brief Return a pointer to the EOD accepts table. */
147#define getAcceptEodTable(lim) \
148 ((const struct NFAAccept *)((const char *)(lim) + (lim)->acceptEodOffset))
149
150#define MAKE_GET_NFA_REPEAT_INFO(size) \
151 static really_inline const struct NFARepeatInfo *getNfaRepeatInfo##size( \
152 const struct LimExNFA##size *limex, unsigned num) { \
153 assert(num < limex->repeatCount); \
154 \
155 const char *base = (const char *)limex; \
156 const u32 *repeatOffset = (const u32 *)(base + limex->repeatOffset); \
157 assert(ISALIGNED(repeatOffset)); \
158 \
159 const struct NFARepeatInfo *info = \
160 (const struct NFARepeatInfo *)(base + repeatOffset[num]); \
161 assert(ISALIGNED(info)); \
162 return info; \
163 }
164
165MAKE_GET_NFA_REPEAT_INFO(32)
166MAKE_GET_NFA_REPEAT_INFO(64)
167MAKE_GET_NFA_REPEAT_INFO(128)
168MAKE_GET_NFA_REPEAT_INFO(256)
169MAKE_GET_NFA_REPEAT_INFO(384)
170MAKE_GET_NFA_REPEAT_INFO(512)
171
172static really_inline
173const struct RepeatInfo *getRepeatInfo(const struct NFARepeatInfo *info) {
174 const struct RepeatInfo *repeat =
175 (const struct RepeatInfo *)((const char *)info + sizeof(*info));
176 assert(ISALIGNED(repeat));
177 return repeat;
178}
179
180static really_inline
181union RepeatControl *getRepeatControlBase(char *state, size_t nfa_state_size) {
182 union RepeatControl *ctrl_base =
183 (union RepeatControl *)(state +
184 ROUNDUP_N(nfa_state_size,
185 alignof(union RepeatControl)));
186 assert(ISALIGNED(ctrl_base));
187 return ctrl_base;
188}
189
190static really_inline
191const union RepeatControl *getRepeatControlBaseConst(const char *state,
192 size_t nfa_state_size) {
193 const union RepeatControl *ctrl_base =
194 (const union RepeatControl *)(state +
195 ROUNDUP_N(nfa_state_size,
196 alignof(union RepeatControl)));
197 assert(ISALIGNED(ctrl_base));
198 return ctrl_base;
199}
200
201#endif
202