1 /*************************************************
2 * Perl-Compatible Regular Expressions *
3 *************************************************/
4
5 /* PCRE is a library of functions to support regular expressions whose syntax
6 and semantics are as close as possible to those of the Perl 5 language.
7
8 Written by Philip Hazel
9 This module by Zoltan Herczeg and Sebastian Pop
10 Original API code Copyright (c) 1997-2012 University of Cambridge
11 New API code Copyright (c) 2016-2019 University of Cambridge
12
13 -----------------------------------------------------------------------------
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions are met:
16
17 * Redistributions of source code must retain the above copyright notice,
18 this list of conditions and the following disclaimer.
19
20 * Redistributions in binary form must reproduce the above copyright
21 notice, this list of conditions and the following disclaimer in the
22 documentation and/or other materials provided with the distribution.
23
24 * Neither the name of the University of Cambridge nor the names of its
25 contributors may be used to endorse or promote products derived from
26 this software without specific prior written permission.
27
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 POSSIBILITY OF SUCH DAMAGE.
39 -----------------------------------------------------------------------------
40 */
41
42 # if defined(FFCS)
43 # if defined(FF_UTF)
44 # define FF_FUN ffcs_utf
45 # else
46 # define FF_FUN ffcs
47 # endif
48
49 # elif defined(FFCS_2)
50 # if defined(FF_UTF)
51 # define FF_FUN ffcs_2_utf
52 # else
53 # define FF_FUN ffcs_2
54 # endif
55
56 # elif defined(FFCS_MASK)
57 # if defined(FF_UTF)
58 # define FF_FUN ffcs_mask_utf
59 # else
60 # define FF_FUN ffcs_mask
61 # endif
62
63 # elif defined(FFCPS_0)
64 # if defined (FF_UTF)
65 # define FF_FUN ffcps_0_utf
66 # else
67 # define FF_FUN ffcps_0
68 # endif
69
70 # elif defined (FFCPS_1)
71 # if defined (FF_UTF)
72 # define FF_FUN ffcps_1_utf
73 # else
74 # define FF_FUN ffcps_1
75 # endif
76
77 # elif defined (FFCPS_DEFAULT)
78 # if defined (FF_UTF)
79 # define FF_FUN ffcps_default_utf
80 # else
81 # define FF_FUN ffcps_default
82 # endif
83 # endif
84
FF_FUN(sljit_u8 * str_end,sljit_u8 * str_ptr,sljit_uw offs1,sljit_uw offs2,sljit_uw chars)85 static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 *str_ptr, sljit_uw offs1, sljit_uw offs2, sljit_uw chars)
86 #undef FF_FUN
87 {
88 quad_word qw;
89 int_char ic;
90
91 SLJIT_UNUSED_ARG(offs1);
92 SLJIT_UNUSED_ARG(offs2);
93
94 ic.x = chars;
95
96 #if defined(FFCS)
97 sljit_u8 c1 = ic.c.c1;
98 vect_t vc1 = VDUPQ(c1);
99
100 #elif defined(FFCS_2)
101 sljit_u8 c1 = ic.c.c1;
102 vect_t vc1 = VDUPQ(c1);
103 sljit_u8 c2 = ic.c.c2;
104 vect_t vc2 = VDUPQ(c2);
105
106 #elif defined(FFCS_MASK)
107 sljit_u8 c1 = ic.c.c1;
108 vect_t vc1 = VDUPQ(c1);
109 sljit_u8 mask = ic.c.c2;
110 vect_t vmask = VDUPQ(mask);
111 #endif
112
113 #if defined(FFCPS)
114 compare_type compare1_type = compare_match1;
115 compare_type compare2_type = compare_match1;
116 vect_t cmp1a, cmp1b, cmp2a, cmp2b;
117 const sljit_u32 diff = IN_UCHARS(offs1 - offs2);
118 PCRE2_UCHAR char1a = ic.c.c1;
119 PCRE2_UCHAR char2a = ic.c.c3;
120
121 # ifdef FFCPS_CHAR1A2A
122 cmp1a = VDUPQ(char1a);
123 cmp2a = VDUPQ(char2a);
124 cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
125 cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
126 # else
127 PCRE2_UCHAR char1b = ic.c.c2;
128 PCRE2_UCHAR char2b = ic.c.c4;
129 if (char1a == char1b)
130 {
131 cmp1a = VDUPQ(char1a);
132 cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
133 }
134 else
135 {
136 sljit_u32 bit1 = char1a ^ char1b;
137 if (is_powerof2(bit1))
138 {
139 compare1_type = compare_match1i;
140 cmp1a = VDUPQ(char1a | bit1);
141 cmp1b = VDUPQ(bit1);
142 }
143 else
144 {
145 compare1_type = compare_match2;
146 cmp1a = VDUPQ(char1a);
147 cmp1b = VDUPQ(char1b);
148 }
149 }
150
151 if (char2a == char2b)
152 {
153 cmp2a = VDUPQ(char2a);
154 cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
155 }
156 else
157 {
158 sljit_u32 bit2 = char2a ^ char2b;
159 if (is_powerof2(bit2))
160 {
161 compare2_type = compare_match1i;
162 cmp2a = VDUPQ(char2a | bit2);
163 cmp2b = VDUPQ(bit2);
164 }
165 else
166 {
167 compare2_type = compare_match2;
168 cmp2a = VDUPQ(char2a);
169 cmp2b = VDUPQ(char2b);
170 }
171 }
172 # endif
173
174 str_ptr += IN_UCHARS(offs1);
175 #endif
176
177 #if PCRE2_CODE_UNIT_WIDTH != 8
178 vect_t char_mask = VDUPQ(0xff);
179 #endif
180
181 #if defined(FF_UTF)
182 restart:;
183 #endif
184
185 #if defined(FFCPS)
186 if (str_ptr >= str_end)
187 return NULL;
188 sljit_u8 *p1 = str_ptr - diff;
189 #endif
190 sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf);
191 str_ptr = (sljit_u8 *) ((uint64_t)str_ptr & ~0xf);
192 vect_t data = VLD1Q(str_ptr);
193 #if PCRE2_CODE_UNIT_WIDTH != 8
194 data = VANDQ(data, char_mask);
195 #endif
196
197 #if defined(FFCS)
198 vect_t eq = VCEQQ(data, vc1);
199
200 #elif defined(FFCS_2)
201 vect_t eq1 = VCEQQ(data, vc1);
202 vect_t eq2 = VCEQQ(data, vc2);
203 vect_t eq = VORRQ(eq1, eq2);
204
205 #elif defined(FFCS_MASK)
206 vect_t eq = VORRQ(data, vmask);
207 eq = VCEQQ(eq, vc1);
208
209 #elif defined(FFCPS)
210 # if defined(FFCPS_DIFF1)
211 vect_t prev_data = data;
212 # endif
213
214 vect_t data2;
215 if (p1 < str_ptr)
216 {
217 data2 = VLD1Q(str_ptr - diff);
218 #if PCRE2_CODE_UNIT_WIDTH != 8
219 data2 = VANDQ(data2, char_mask);
220 #endif
221 }
222 else
223 data2 = shift_left_n_lanes(data, offs1 - offs2);
224
225 if (compare1_type == compare_match1)
226 data = VCEQQ(data, cmp1a);
227 else
228 data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
229
230 if (compare2_type == compare_match1)
231 data2 = VCEQQ(data2, cmp2a);
232 else
233 data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
234
235 vect_t eq = VANDQ(data, data2);
236 #endif
237
238 VST1Q(qw.mem, eq);
239 /* Ignore matches before the first STR_PTR. */
240 if (align_offset < 8)
241 {
242 qw.dw[0] >>= align_offset * 8;
243 if (qw.dw[0])
244 {
245 str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;
246 goto match;
247 }
248 if (qw.dw[1])
249 {
250 str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
251 goto match;
252 }
253 }
254 else
255 {
256 qw.dw[1] >>= (align_offset - 8) * 8;
257 if (qw.dw[1])
258 {
259 str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;
260 goto match;
261 }
262 }
263 str_ptr += 16;
264
265 while (str_ptr < str_end)
266 {
267 vect_t orig_data = VLD1Q(str_ptr);
268 #if PCRE2_CODE_UNIT_WIDTH != 8
269 orig_data = VANDQ(orig_data, char_mask);
270 #endif
271 data = orig_data;
272
273 #if defined(FFCS)
274 eq = VCEQQ(data, vc1);
275
276 #elif defined(FFCS_2)
277 eq1 = VCEQQ(data, vc1);
278 eq2 = VCEQQ(data, vc2);
279 eq = VORRQ(eq1, eq2);
280
281 #elif defined(FFCS_MASK)
282 eq = VORRQ(data, vmask);
283 eq = VCEQQ(eq, vc1);
284 #endif
285
286 #if defined(FFCPS)
287 # if defined (FFCPS_DIFF1)
288 data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);
289 # else
290 data2 = VLD1Q(str_ptr - diff);
291 # if PCRE2_CODE_UNIT_WIDTH != 8
292 data2 = VANDQ(data2, char_mask);
293 # endif
294 # endif
295
296 # ifdef FFCPS_CHAR1A2A
297 data = VCEQQ(data, cmp1a);
298 data2 = VCEQQ(data2, cmp2a);
299 # else
300 if (compare1_type == compare_match1)
301 data = VCEQQ(data, cmp1a);
302 else
303 data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
304 if (compare2_type == compare_match1)
305 data2 = VCEQQ(data2, cmp2a);
306 else
307 data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
308 # endif
309
310 eq = VANDQ(data, data2);
311 #endif
312
313 VST1Q(qw.mem, eq);
314 if (qw.dw[0])
315 str_ptr += __builtin_ctzll(qw.dw[0]) / 8;
316 else if (qw.dw[1])
317 str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
318 else {
319 str_ptr += 16;
320 #if defined (FFCPS_DIFF1)
321 prev_data = orig_data;
322 #endif
323 continue;
324 }
325
326 match:;
327 if (str_ptr >= str_end)
328 /* Failed match. */
329 return NULL;
330
331 #if defined(FF_UTF)
332 if (utf_continue((PCRE2_SPTR)str_ptr - offs1))
333 {
334 /* Not a match. */
335 str_ptr += IN_UCHARS(1);
336 goto restart;
337 }
338 #endif
339
340 /* Match. */
341 #if defined (FFCPS)
342 str_ptr -= IN_UCHARS(offs1);
343 #endif
344 return str_ptr;
345 }
346
347 /* Failed match. */
348 return NULL;
349 }
350