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 sljit_u8 *p1 = str_ptr - diff;
187 #endif
188 sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf);
189 str_ptr = (sljit_u8 *) ((uint64_t)str_ptr & ~0xf);
190 vect_t data = VLD1Q(str_ptr);
191 #if PCRE2_CODE_UNIT_WIDTH != 8
192 data = VANDQ(data, char_mask);
193 #endif
194
195 #if defined(FFCS)
196 vect_t eq = VCEQQ(data, vc1);
197
198 #elif defined(FFCS_2)
199 vect_t eq1 = VCEQQ(data, vc1);
200 vect_t eq2 = VCEQQ(data, vc2);
201 vect_t eq = VORRQ(eq1, eq2);
202
203 #elif defined(FFCS_MASK)
204 vect_t eq = VORRQ(data, vmask);
205 eq = VCEQQ(eq, vc1);
206
207 #elif defined(FFCPS)
208 # if defined(FFCPS_DIFF1)
209 vect_t prev_data = data;
210 # endif
211
212 vect_t data2;
213 if (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 }
220 else
221 data2 = shift_left_n_lanes(data, offs1 - offs2);
222
223 if (compare1_type == compare_match1)
224 data = VCEQQ(data, cmp1a);
225 else
226 data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
227
228 if (compare2_type == compare_match1)
229 data2 = VCEQQ(data2, cmp2a);
230 else
231 data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
232
233 vect_t eq = VANDQ(data, data2);
234 #endif
235
236 VST1Q(qw.mem, eq);
237 /* Ignore matches before the first STR_PTR. */
238 if (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 }
252 else
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 }
261 str_ptr += 16;
262
263 while (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
324 match:;
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. */
346 return NULL;
347 }
348