blob: 150da29eba7aa615adc7112c888e27a69da69aee [file] [log] [blame]
Elliott Hughes2dbd7d22020-06-03 14:32:37 -07001/*************************************************
2* Perl-Compatible Regular Expressions *
3*************************************************/
4
5/* PCRE is a library of functions to support regular expressions whose syntax
6and 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-----------------------------------------------------------------------------
14Redistribution and use in source and binary forms, with or without
15modification, 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
28THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38POSSIBILITY 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
85static 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{
88quad_word qw;
89int_char ic;
Elliott Hughes3435c422020-12-04 13:18:28 -080090
91SLJIT_UNUSED_ARG(offs1);
92SLJIT_UNUSED_ARG(offs2);
93
Elliott Hughes2dbd7d22020-06-03 14:32:37 -070094ic.x = chars;
95
96#if defined(FFCS)
97sljit_u8 c1 = ic.c.c1;
98vect_t vc1 = VDUPQ(c1);
99
100#elif defined(FFCS_2)
101sljit_u8 c1 = ic.c.c1;
102vect_t vc1 = VDUPQ(c1);
103sljit_u8 c2 = ic.c.c2;
104vect_t vc2 = VDUPQ(c2);
105
106#elif defined(FFCS_MASK)
107sljit_u8 c1 = ic.c.c1;
108vect_t vc1 = VDUPQ(c1);
109sljit_u8 mask = ic.c.c2;
110vect_t vmask = VDUPQ(mask);
111#endif
112
113#if defined(FFCPS)
114compare_type compare1_type = compare_match1;
115compare_type compare2_type = compare_match1;
116vect_t cmp1a, cmp1b, cmp2a, cmp2b;
117const sljit_u32 diff = IN_UCHARS(offs1 - offs2);
118PCRE2_UCHAR char1a = ic.c.c1;
119PCRE2_UCHAR char2a = ic.c.c3;
120
121# ifdef FFCPS_CHAR1A2A
122cmp1a = VDUPQ(char1a);
123cmp2a = VDUPQ(char2a);
124cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
125cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
126# else
127PCRE2_UCHAR char1b = ic.c.c2;
128PCRE2_UCHAR char2b = ic.c.c4;
129if (char1a == char1b)
130 {
131 cmp1a = VDUPQ(char1a);
132 cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
133 }
134else
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
151if (char2a == char2b)
152 {
153 cmp2a = VDUPQ(char2a);
154 cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
155 }
156else
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
174str_ptr += IN_UCHARS(offs1);
175#endif
176
177#if PCRE2_CODE_UNIT_WIDTH != 8
178vect_t char_mask = VDUPQ(0xff);
179#endif
180
181#if defined(FF_UTF)
182restart:;
183#endif
184
185#if defined(FFCPS)
186sljit_u8 *p1 = str_ptr - diff;
187#endif
188sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf);
189str_ptr = (sljit_u8 *) ((uint64_t)str_ptr & ~0xf);
190vect_t data = VLD1Q(str_ptr);
191#if PCRE2_CODE_UNIT_WIDTH != 8
192data = VANDQ(data, char_mask);
193#endif
194
195#if defined(FFCS)
196vect_t eq = VCEQQ(data, vc1);
197
198#elif defined(FFCS_2)
199vect_t eq1 = VCEQQ(data, vc1);
200vect_t eq2 = VCEQQ(data, vc2);
201vect_t eq = VORRQ(eq1, eq2);
202
203#elif defined(FFCS_MASK)
204vect_t eq = VORRQ(data, vmask);
205eq = VCEQQ(eq, vc1);
206
207#elif defined(FFCPS)
208# if defined(FFCPS_DIFF1)
209vect_t prev_data = data;
210# endif
211
212vect_t data2;
213if (p1 < str_ptr)
214 {
215 data2 = VLD1Q(str_ptr - diff);
216#if PCRE2_CODE_UNIT_WIDTH != 8
217 data2 = VANDQ(data2, char_mask);
218#endif
219 }
220else
221 data2 = shift_left_n_lanes(data, offs1 - offs2);
222
223if (compare1_type == compare_match1)
224 data = VCEQQ(data, cmp1a);
225else
226 data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
227
228if (compare2_type == compare_match1)
229 data2 = VCEQQ(data2, cmp2a);
230else
231 data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
232
233vect_t eq = VANDQ(data, data2);
234#endif
235
236VST1Q(qw.mem, eq);
237/* Ignore matches before the first STR_PTR. */
238if (align_offset < 8)
239 {
240 qw.dw[0] >>= align_offset * 8;
241 if (qw.dw[0])
242 {
243 str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;
244 goto match;
245 }
246 if (qw.dw[1])
247 {
248 str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
249 goto match;
250 }
251 }
252else
253 {
254 qw.dw[1] >>= (align_offset - 8) * 8;
255 if (qw.dw[1])
256 {
257 str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;
258 goto match;
259 }
260 }
261str_ptr += 16;
262
263while (str_ptr < str_end)
264 {
265 vect_t orig_data = VLD1Q(str_ptr);
266#if PCRE2_CODE_UNIT_WIDTH != 8
267 orig_data = VANDQ(orig_data, char_mask);
268#endif
269 data = orig_data;
270
271#if defined(FFCS)
272 eq = VCEQQ(data, vc1);
273
274#elif defined(FFCS_2)
275 eq1 = VCEQQ(data, vc1);
276 eq2 = VCEQQ(data, vc2);
277 eq = VORRQ(eq1, eq2);
278
279#elif defined(FFCS_MASK)
280 eq = VORRQ(data, vmask);
281 eq = VCEQQ(eq, vc1);
282#endif
283
284#if defined(FFCPS)
285# if defined (FFCPS_DIFF1)
286 data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);
287# else
288 data2 = VLD1Q(str_ptr - diff);
289# if PCRE2_CODE_UNIT_WIDTH != 8
290 data2 = VANDQ(data2, char_mask);
291# endif
292# endif
293
294# ifdef FFCPS_CHAR1A2A
295 data = VCEQQ(data, cmp1a);
296 data2 = VCEQQ(data2, cmp2a);
297# else
298 if (compare1_type == compare_match1)
299 data = VCEQQ(data, cmp1a);
300 else
301 data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
302 if (compare2_type == compare_match1)
303 data2 = VCEQQ(data2, cmp2a);
304 else
305 data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
306# endif
307
308 eq = VANDQ(data, data2);
309#endif
310
311 VST1Q(qw.mem, eq);
312 if (qw.dw[0])
313 str_ptr += __builtin_ctzll(qw.dw[0]) / 8;
314 else if (qw.dw[1])
315 str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
316 else {
317 str_ptr += 16;
318#if defined (FFCPS_DIFF1)
319 prev_data = orig_data;
320#endif
321 continue;
322 }
323
324match:;
325 if (str_ptr >= str_end)
326 /* Failed match. */
327 return NULL;
328
329#if defined(FF_UTF)
330 if (utf_continue(str_ptr + IN_UCHARS(-offs1)))
331 {
332 /* Not a match. */
333 str_ptr += IN_UCHARS(1);
334 goto restart;
335 }
336#endif
337
338 /* Match. */
339#if defined (FFCPS)
340 str_ptr -= IN_UCHARS(offs1);
341#endif
342 return str_ptr;
343 }
344
345/* Failed match. */
346return NULL;
347}