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 ic.x = chars;
91
92 #if defined(FFCS)
93 sljit_u8 c1 = ic.c.c1;
94 vect_t vc1 = VDUPQ(c1);
95
96 #elif defined(FFCS_2)
97 sljit_u8 c1 = ic.c.c1;
98 vect_t vc1 = VDUPQ(c1);
99 sljit_u8 c2 = ic.c.c2;
100 vect_t vc2 = VDUPQ(c2);
101
102 #elif defined(FFCS_MASK)
103 sljit_u8 c1 = ic.c.c1;
104 vect_t vc1 = VDUPQ(c1);
105 sljit_u8 mask = ic.c.c2;
106 vect_t vmask = VDUPQ(mask);
107 #endif
108
109 #if defined(FFCPS)
110 compare_type compare1_type = compare_match1;
111 compare_type compare2_type = compare_match1;
112 vect_t cmp1a, cmp1b, cmp2a, cmp2b;
113 const sljit_u32 diff = IN_UCHARS(offs1 - offs2);
114 PCRE2_UCHAR char1a = ic.c.c1;
115 PCRE2_UCHAR char2a = ic.c.c3;
116
117 # ifdef FFCPS_CHAR1A2A
118 cmp1a = VDUPQ(char1a);
119 cmp2a = VDUPQ(char2a);
120 cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
121 cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
122 # else
123 PCRE2_UCHAR char1b = ic.c.c2;
124 PCRE2_UCHAR char2b = ic.c.c4;
125 if (char1a == char1b)
126 {
127 cmp1a = VDUPQ(char1a);
128 cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
129 }
130 else
131 {
132 sljit_u32 bit1 = char1a ^ char1b;
133 if (is_powerof2(bit1))
134 {
135 compare1_type = compare_match1i;
136 cmp1a = VDUPQ(char1a | bit1);
137 cmp1b = VDUPQ(bit1);
138 }
139 else
140 {
141 compare1_type = compare_match2;
142 cmp1a = VDUPQ(char1a);
143 cmp1b = VDUPQ(char1b);
144 }
145 }
146
147 if (char2a == char2b)
148 {
149 cmp2a = VDUPQ(char2a);
150 cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
151 }
152 else
153 {
154 sljit_u32 bit2 = char2a ^ char2b;
155 if (is_powerof2(bit2))
156 {
157 compare2_type = compare_match1i;
158 cmp2a = VDUPQ(char2a | bit2);
159 cmp2b = VDUPQ(bit2);
160 }
161 else
162 {
163 compare2_type = compare_match2;
164 cmp2a = VDUPQ(char2a);
165 cmp2b = VDUPQ(char2b);
166 }
167 }
168 # endif
169
170 str_ptr += IN_UCHARS(offs1);
171 #endif
172
173 #if PCRE2_CODE_UNIT_WIDTH != 8
174 vect_t char_mask = VDUPQ(0xff);
175 #endif
176
177 #if defined(FF_UTF)
178 restart:;
179 #endif
180
181 #if defined(FFCPS)
182 sljit_u8 *p1 = str_ptr - diff;
183 #endif
184 sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf);
185 str_ptr = (sljit_u8 *) ((uint64_t)str_ptr & ~0xf);
186 vect_t data = VLD1Q(str_ptr);
187 #if PCRE2_CODE_UNIT_WIDTH != 8
188 data = VANDQ(data, char_mask);
189 #endif
190
191 #if defined(FFCS)
192 vect_t eq = VCEQQ(data, vc1);
193
194 #elif defined(FFCS_2)
195 vect_t eq1 = VCEQQ(data, vc1);
196 vect_t eq2 = VCEQQ(data, vc2);
197 vect_t eq = VORRQ(eq1, eq2);
198
199 #elif defined(FFCS_MASK)
200 vect_t eq = VORRQ(data, vmask);
201 eq = VCEQQ(eq, vc1);
202
203 #elif defined(FFCPS)
204 # if defined(FFCPS_DIFF1)
205 vect_t prev_data = data;
206 # endif
207
208 vect_t data2;
209 if (p1 < str_ptr)
210 {
211 data2 = VLD1Q(str_ptr - diff);
212 #if PCRE2_CODE_UNIT_WIDTH != 8
213 data2 = VANDQ(data2, char_mask);
214 #endif
215 }
216 else
217 data2 = shift_left_n_lanes(data, offs1 - offs2);
218
219 if (compare1_type == compare_match1)
220 data = VCEQQ(data, cmp1a);
221 else
222 data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
223
224 if (compare2_type == compare_match1)
225 data2 = VCEQQ(data2, cmp2a);
226 else
227 data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
228
229 vect_t eq = VANDQ(data, data2);
230 #endif
231
232 VST1Q(qw.mem, eq);
233 /* Ignore matches before the first STR_PTR. */
234 if (align_offset < 8)
235 {
236 qw.dw[0] >>= align_offset * 8;
237 if (qw.dw[0])
238 {
239 str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;
240 goto match;
241 }
242 if (qw.dw[1])
243 {
244 str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
245 goto match;
246 }
247 }
248 else
249 {
250 qw.dw[1] >>= (align_offset - 8) * 8;
251 if (qw.dw[1])
252 {
253 str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;
254 goto match;
255 }
256 }
257 str_ptr += 16;
258
259 while (str_ptr < str_end)
260 {
261 vect_t orig_data = VLD1Q(str_ptr);
262 #if PCRE2_CODE_UNIT_WIDTH != 8
263 orig_data = VANDQ(orig_data, char_mask);
264 #endif
265 data = orig_data;
266
267 #if defined(FFCS)
268 eq = VCEQQ(data, vc1);
269
270 #elif defined(FFCS_2)
271 eq1 = VCEQQ(data, vc1);
272 eq2 = VCEQQ(data, vc2);
273 eq = VORRQ(eq1, eq2);
274
275 #elif defined(FFCS_MASK)
276 eq = VORRQ(data, vmask);
277 eq = VCEQQ(eq, vc1);
278 #endif
279
280 #if defined(FFCPS)
281 # if defined (FFCPS_DIFF1)
282 data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);
283 # else
284 data2 = VLD1Q(str_ptr - diff);
285 # if PCRE2_CODE_UNIT_WIDTH != 8
286 data2 = VANDQ(data2, char_mask);
287 # endif
288 # endif
289
290 # ifdef FFCPS_CHAR1A2A
291 data = VCEQQ(data, cmp1a);
292 data2 = VCEQQ(data2, cmp2a);
293 # else
294 if (compare1_type == compare_match1)
295 data = VCEQQ(data, cmp1a);
296 else
297 data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
298 if (compare2_type == compare_match1)
299 data2 = VCEQQ(data2, cmp2a);
300 else
301 data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
302 # endif
303
304 eq = VANDQ(data, data2);
305 #endif
306
307 VST1Q(qw.mem, eq);
308 if (qw.dw[0])
309 str_ptr += __builtin_ctzll(qw.dw[0]) / 8;
310 else if (qw.dw[1])
311 str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
312 else {
313 str_ptr += 16;
314 #if defined (FFCPS_DIFF1)
315 prev_data = orig_data;
316 #endif
317 continue;
318 }
319
320 match:;
321 if (str_ptr >= str_end)
322 /* Failed match. */
323 return NULL;
324
325 #if defined(FF_UTF)
326 if (utf_continue(str_ptr + IN_UCHARS(-offs1)))
327 {
328 /* Not a match. */
329 str_ptr += IN_UCHARS(1);
330 goto restart;
331 }
332 #endif
333
334 /* Match. */
335 #if defined (FFCPS)
336 str_ptr -= IN_UCHARS(offs1);
337 #endif
338 return str_ptr;
339 }
340
341 /* Failed match. */
342 return NULL;
343 }
344