1 | /* |
2 | * Copyright (c) 2017-2018, 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 | #include "rose_build_instructions.h" |
30 | |
31 | #include "rose_build_engine_blob.h" |
32 | #include "util/multibit_build.h" |
33 | #include "util/verify_types.h" |
34 | |
35 | #include <algorithm> |
36 | |
37 | using namespace std; |
38 | |
39 | namespace ue2 { |
40 | /* Destructors to avoid weak vtables. */ |
41 | |
42 | RoseInstruction::~RoseInstruction() = default; |
43 | RoseInstrCatchUp::~RoseInstrCatchUp() = default; |
44 | RoseInstrCatchUpMpv::~RoseInstrCatchUpMpv() = default; |
45 | RoseInstrSomZero::~RoseInstrSomZero() = default; |
46 | RoseInstrSuffixesEod::~RoseInstrSuffixesEod() = default; |
47 | RoseInstrMatcherEod::~RoseInstrMatcherEod() = default; |
48 | RoseInstrEnd::~RoseInstrEnd() = default; |
49 | RoseInstrClearWorkDone::~RoseInstrClearWorkDone() = default; |
50 | RoseInstrFlushCombination::~RoseInstrFlushCombination() = default; |
51 | |
52 | using OffsetMap = RoseInstruction::OffsetMap; |
53 | |
54 | static |
55 | u32 calc_jump(const OffsetMap &offset_map, const RoseInstruction *from, |
56 | const RoseInstruction *to) { |
57 | DEBUG_PRINTF("computing relative jump from %p to %p\n" , from, to); |
58 | assert(from && contains(offset_map, from)); |
59 | assert(to && contains(offset_map, to)); |
60 | |
61 | u32 from_offset = offset_map.at(from); |
62 | u32 to_offset = offset_map.at(to); |
63 | DEBUG_PRINTF("offsets: %u -> %u\n" , from_offset, to_offset); |
64 | assert(from_offset <= to_offset); |
65 | |
66 | return to_offset - from_offset; |
67 | } |
68 | |
69 | void RoseInstrAnchoredDelay::write(void *dest, RoseEngineBlob &blob, |
70 | const OffsetMap &offset_map) const { |
71 | RoseInstrBase::write(dest, blob, offset_map); |
72 | auto *inst = static_cast<impl_type *>(dest); |
73 | inst->groups = groups; |
74 | inst->anch_id = anch_id; |
75 | inst->done_jump = calc_jump(offset_map, this, target); |
76 | } |
77 | |
78 | void RoseInstrCheckLitEarly::write(void *dest, RoseEngineBlob &blob, |
79 | const OffsetMap &offset_map) const { |
80 | RoseInstrBase::write(dest, blob, offset_map); |
81 | auto *inst = static_cast<impl_type *>(dest); |
82 | inst->min_offset = min_offset; |
83 | inst->fail_jump = calc_jump(offset_map, this, target); |
84 | } |
85 | |
86 | void RoseInstrCheckGroups::write(void *dest, RoseEngineBlob &blob, |
87 | const OffsetMap &offset_map) const { |
88 | RoseInstrBase::write(dest, blob, offset_map); |
89 | auto *inst = static_cast<impl_type *>(dest); |
90 | inst->groups = groups; |
91 | } |
92 | |
93 | void RoseInstrCheckOnlyEod::write(void *dest, RoseEngineBlob &blob, |
94 | const OffsetMap &offset_map) const { |
95 | RoseInstrBase::write(dest, blob, offset_map); |
96 | auto *inst = static_cast<impl_type *>(dest); |
97 | inst->fail_jump = calc_jump(offset_map, this, target); |
98 | } |
99 | |
100 | void RoseInstrCheckBounds::write(void *dest, RoseEngineBlob &blob, |
101 | const OffsetMap &offset_map) const { |
102 | RoseInstrBase::write(dest, blob, offset_map); |
103 | auto *inst = static_cast<impl_type *>(dest); |
104 | inst->min_bound = min_bound; |
105 | inst->max_bound = max_bound; |
106 | inst->fail_jump = calc_jump(offset_map, this, target); |
107 | } |
108 | |
109 | void RoseInstrCheckNotHandled::write(void *dest, RoseEngineBlob &blob, |
110 | const OffsetMap &offset_map) const { |
111 | RoseInstrBase::write(dest, blob, offset_map); |
112 | auto *inst = static_cast<impl_type *>(dest); |
113 | inst->key = key; |
114 | inst->fail_jump = calc_jump(offset_map, this, target); |
115 | } |
116 | |
117 | void RoseInstrCheckSingleLookaround::write(void *dest, RoseEngineBlob &blob, |
118 | const OffsetMap &offset_map) const { |
119 | RoseInstrBase::write(dest, blob, offset_map); |
120 | auto *inst = static_cast<impl_type *>(dest); |
121 | inst->offset = offset; |
122 | inst->reach_index = blob.lookaround_cache.get_offset_of({reach}, blob); |
123 | inst->fail_jump = calc_jump(offset_map, this, target); |
124 | } |
125 | |
126 | void RoseInstrCheckLookaround::write(void *dest, RoseEngineBlob &blob, |
127 | const OffsetMap &offset_map) const { |
128 | RoseInstrBase::write(dest, blob, offset_map); |
129 | auto *inst = static_cast<impl_type *>(dest); |
130 | vector<s8> look_offsets; |
131 | vector<CharReach> reaches; |
132 | for (const auto &le : look) { |
133 | look_offsets.push_back(le.offset); |
134 | reaches.push_back(le.reach); |
135 | } |
136 | inst->look_index = blob.lookaround_cache.get_offset_of(look_offsets, blob); |
137 | inst->reach_index = blob.lookaround_cache.get_offset_of(reaches, blob); |
138 | inst->count = verify_u32(look.size()); |
139 | inst->fail_jump = calc_jump(offset_map, this, target); |
140 | } |
141 | |
142 | void RoseInstrCheckMask::write(void *dest, RoseEngineBlob &blob, |
143 | const OffsetMap &offset_map) const { |
144 | RoseInstrBase::write(dest, blob, offset_map); |
145 | auto *inst = static_cast<impl_type *>(dest); |
146 | inst->and_mask = and_mask; |
147 | inst->cmp_mask = cmp_mask; |
148 | inst->neg_mask = neg_mask; |
149 | inst->offset = offset; |
150 | inst->fail_jump = calc_jump(offset_map, this, target); |
151 | } |
152 | |
153 | void RoseInstrCheckMask32::write(void *dest, RoseEngineBlob &blob, |
154 | const OffsetMap &offset_map) const { |
155 | RoseInstrBase::write(dest, blob, offset_map); |
156 | auto *inst = static_cast<impl_type *>(dest); |
157 | copy(begin(and_mask), end(and_mask), inst->and_mask); |
158 | copy(begin(cmp_mask), end(cmp_mask), inst->cmp_mask); |
159 | inst->neg_mask = neg_mask; |
160 | inst->offset = offset; |
161 | inst->fail_jump = calc_jump(offset_map, this, target); |
162 | } |
163 | |
164 | void RoseInstrCheckByte::write(void *dest, RoseEngineBlob &blob, |
165 | const OffsetMap &offset_map) const { |
166 | RoseInstrBase::write(dest, blob, offset_map); |
167 | auto *inst = static_cast<impl_type *>(dest); |
168 | inst->and_mask = and_mask; |
169 | inst->cmp_mask = cmp_mask; |
170 | inst->negation = negation; |
171 | inst->offset = offset; |
172 | inst->fail_jump = calc_jump(offset_map, this, target); |
173 | } |
174 | |
175 | void RoseInstrCheckShufti16x8::write(void *dest, RoseEngineBlob &blob, |
176 | const OffsetMap &offset_map) const { |
177 | RoseInstrBase::write(dest, blob, offset_map); |
178 | auto *inst = static_cast<impl_type *>(dest); |
179 | copy(begin(nib_mask), end(nib_mask), inst->nib_mask); |
180 | copy(begin(bucket_select_mask), end(bucket_select_mask), |
181 | inst->bucket_select_mask); |
182 | inst->neg_mask = neg_mask; |
183 | inst->offset = offset; |
184 | inst->fail_jump = calc_jump(offset_map, this, target); |
185 | } |
186 | |
187 | void RoseInstrCheckShufti32x8::write(void *dest, RoseEngineBlob &blob, |
188 | const OffsetMap &offset_map) const { |
189 | RoseInstrBase::write(dest, blob, offset_map); |
190 | auto *inst = static_cast<impl_type *>(dest); |
191 | copy(begin(hi_mask), end(hi_mask), inst->hi_mask); |
192 | copy(begin(lo_mask), end(lo_mask), inst->lo_mask); |
193 | copy(begin(bucket_select_mask), end(bucket_select_mask), |
194 | inst->bucket_select_mask); |
195 | |
196 | inst->neg_mask = neg_mask; |
197 | inst->offset = offset; |
198 | inst->fail_jump = calc_jump(offset_map, this, target); |
199 | } |
200 | |
201 | void RoseInstrCheckShufti16x16::write(void *dest, RoseEngineBlob &blob, |
202 | const OffsetMap &offset_map) const { |
203 | RoseInstrBase::write(dest, blob, offset_map); |
204 | auto *inst = static_cast<impl_type *>(dest); |
205 | copy(begin(hi_mask), end(hi_mask), inst->hi_mask); |
206 | copy(begin(lo_mask), end(lo_mask), inst->lo_mask); |
207 | copy(begin(bucket_select_mask), end(bucket_select_mask), |
208 | inst->bucket_select_mask); |
209 | inst->neg_mask = neg_mask; |
210 | inst->offset = offset; |
211 | inst->fail_jump = calc_jump(offset_map, this, target); |
212 | } |
213 | |
214 | void RoseInstrCheckShufti32x16::write(void *dest, RoseEngineBlob &blob, |
215 | const OffsetMap &offset_map) const { |
216 | RoseInstrBase::write(dest, blob, offset_map); |
217 | auto *inst = static_cast<impl_type *>(dest); |
218 | copy(begin(hi_mask), end(hi_mask), inst->hi_mask); |
219 | copy(begin(lo_mask), end(lo_mask), inst->lo_mask); |
220 | copy(begin(bucket_select_mask_hi), end(bucket_select_mask_hi), |
221 | inst->bucket_select_mask_hi); |
222 | copy(begin(bucket_select_mask_lo), end(bucket_select_mask_lo), |
223 | inst->bucket_select_mask_lo); |
224 | inst->neg_mask = neg_mask; |
225 | inst->offset = offset; |
226 | inst->fail_jump = calc_jump(offset_map, this, target); |
227 | } |
228 | |
229 | void RoseInstrCheckInfix::write(void *dest, RoseEngineBlob &blob, |
230 | const OffsetMap &offset_map) const { |
231 | RoseInstrBase::write(dest, blob, offset_map); |
232 | auto *inst = static_cast<impl_type *>(dest); |
233 | inst->queue = queue; |
234 | inst->lag = lag; |
235 | inst->report = report; |
236 | inst->fail_jump = calc_jump(offset_map, this, target); |
237 | } |
238 | |
239 | void RoseInstrCheckPrefix::write(void *dest, RoseEngineBlob &blob, |
240 | const OffsetMap &offset_map) const { |
241 | RoseInstrBase::write(dest, blob, offset_map); |
242 | auto *inst = static_cast<impl_type *>(dest); |
243 | inst->queue = queue; |
244 | inst->lag = lag; |
245 | inst->report = report; |
246 | inst->fail_jump = calc_jump(offset_map, this, target); |
247 | } |
248 | |
249 | void RoseInstrPushDelayed::write(void *dest, RoseEngineBlob &blob, |
250 | const OffsetMap &offset_map) const { |
251 | RoseInstrBase::write(dest, blob, offset_map); |
252 | auto *inst = static_cast<impl_type *>(dest); |
253 | inst->delay = delay; |
254 | inst->index = index; |
255 | } |
256 | |
257 | void RoseInstrSomAdjust::write(void *dest, RoseEngineBlob &blob, |
258 | const OffsetMap &offset_map) const { |
259 | RoseInstrBase::write(dest, blob, offset_map); |
260 | auto *inst = static_cast<impl_type *>(dest); |
261 | inst->distance = distance; |
262 | } |
263 | |
264 | void RoseInstrSomLeftfix::write(void *dest, RoseEngineBlob &blob, |
265 | const OffsetMap &offset_map) const { |
266 | RoseInstrBase::write(dest, blob, offset_map); |
267 | auto *inst = static_cast<impl_type *>(dest); |
268 | inst->queue = queue; |
269 | inst->lag = lag; |
270 | } |
271 | |
272 | void RoseInstrSomFromReport::write(void *dest, RoseEngineBlob &blob, |
273 | const OffsetMap &offset_map) const { |
274 | RoseInstrBase::write(dest, blob, offset_map); |
275 | auto *inst = static_cast<impl_type *>(dest); |
276 | inst->som = som; |
277 | } |
278 | |
279 | void RoseInstrTriggerInfix::write(void *dest, RoseEngineBlob &blob, |
280 | const OffsetMap &offset_map) const { |
281 | RoseInstrBase::write(dest, blob, offset_map); |
282 | auto *inst = static_cast<impl_type *>(dest); |
283 | inst->cancel = cancel; |
284 | inst->queue = queue; |
285 | inst->event = event; |
286 | } |
287 | |
288 | void RoseInstrTriggerSuffix::write(void *dest, RoseEngineBlob &blob, |
289 | const OffsetMap &offset_map) const { |
290 | RoseInstrBase::write(dest, blob, offset_map); |
291 | auto *inst = static_cast<impl_type *>(dest); |
292 | inst->queue = queue; |
293 | inst->event = event; |
294 | } |
295 | |
296 | void RoseInstrDedupe::write(void *dest, RoseEngineBlob &blob, |
297 | const OffsetMap &offset_map) const { |
298 | RoseInstrBase::write(dest, blob, offset_map); |
299 | auto *inst = static_cast<impl_type *>(dest); |
300 | inst->quash_som = quash_som; |
301 | inst->dkey = dkey; |
302 | inst->offset_adjust = offset_adjust; |
303 | inst->fail_jump = calc_jump(offset_map, this, target); |
304 | } |
305 | |
306 | void RoseInstrDedupeSom::write(void *dest, RoseEngineBlob &blob, |
307 | const OffsetMap &offset_map) const { |
308 | RoseInstrBase::write(dest, blob, offset_map); |
309 | auto *inst = static_cast<impl_type *>(dest); |
310 | inst->quash_som = quash_som; |
311 | inst->dkey = dkey; |
312 | inst->offset_adjust = offset_adjust; |
313 | inst->fail_jump = calc_jump(offset_map, this, target); |
314 | } |
315 | |
316 | void RoseInstrReportChain::write(void *dest, RoseEngineBlob &blob, |
317 | const OffsetMap &offset_map) const { |
318 | RoseInstrBase::write(dest, blob, offset_map); |
319 | auto *inst = static_cast<impl_type *>(dest); |
320 | inst->event = event; |
321 | inst->top_squash_distance = top_squash_distance; |
322 | } |
323 | |
324 | void RoseInstrReportSomInt::write(void *dest, RoseEngineBlob &blob, |
325 | const OffsetMap &offset_map) const { |
326 | RoseInstrBase::write(dest, blob, offset_map); |
327 | auto *inst = static_cast<impl_type *>(dest); |
328 | inst->som = som; |
329 | } |
330 | |
331 | void RoseInstrReportSomAware::write(void *dest, RoseEngineBlob &blob, |
332 | const OffsetMap &offset_map) const { |
333 | RoseInstrBase::write(dest, blob, offset_map); |
334 | auto *inst = static_cast<impl_type *>(dest); |
335 | inst->som = som; |
336 | } |
337 | |
338 | void RoseInstrReport::write(void *dest, RoseEngineBlob &blob, |
339 | const OffsetMap &offset_map) const { |
340 | RoseInstrBase::write(dest, blob, offset_map); |
341 | auto *inst = static_cast<impl_type *>(dest); |
342 | inst->onmatch = onmatch; |
343 | inst->offset_adjust = offset_adjust; |
344 | } |
345 | |
346 | void RoseInstrReportExhaust::write(void *dest, RoseEngineBlob &blob, |
347 | const OffsetMap &offset_map) const { |
348 | RoseInstrBase::write(dest, blob, offset_map); |
349 | auto *inst = static_cast<impl_type *>(dest); |
350 | inst->onmatch = onmatch; |
351 | inst->offset_adjust = offset_adjust; |
352 | inst->ekey = ekey; |
353 | } |
354 | |
355 | void RoseInstrReportSom::write(void *dest, RoseEngineBlob &blob, |
356 | const OffsetMap &offset_map) const { |
357 | RoseInstrBase::write(dest, blob, offset_map); |
358 | auto *inst = static_cast<impl_type *>(dest); |
359 | inst->onmatch = onmatch; |
360 | inst->offset_adjust = offset_adjust; |
361 | } |
362 | |
363 | void RoseInstrReportSomExhaust::write(void *dest, RoseEngineBlob &blob, |
364 | const OffsetMap &offset_map) const { |
365 | RoseInstrBase::write(dest, blob, offset_map); |
366 | auto *inst = static_cast<impl_type *>(dest); |
367 | inst->onmatch = onmatch; |
368 | inst->offset_adjust = offset_adjust; |
369 | inst->ekey = ekey; |
370 | } |
371 | |
372 | void RoseInstrDedupeAndReport::write(void *dest, RoseEngineBlob &blob, |
373 | const OffsetMap &offset_map) const { |
374 | RoseInstrBase::write(dest, blob, offset_map); |
375 | auto *inst = static_cast<impl_type *>(dest); |
376 | inst->quash_som = quash_som; |
377 | inst->dkey = dkey; |
378 | inst->onmatch = onmatch; |
379 | inst->offset_adjust = offset_adjust; |
380 | inst->fail_jump = calc_jump(offset_map, this, target); |
381 | } |
382 | |
383 | void RoseInstrFinalReport::write(void *dest, RoseEngineBlob &blob, |
384 | const OffsetMap &offset_map) const { |
385 | RoseInstrBase::write(dest, blob, offset_map); |
386 | auto *inst = static_cast<impl_type *>(dest); |
387 | inst->onmatch = onmatch; |
388 | inst->offset_adjust = offset_adjust; |
389 | } |
390 | |
391 | void RoseInstrCheckExhausted::write(void *dest, RoseEngineBlob &blob, |
392 | const OffsetMap &offset_map) const { |
393 | RoseInstrBase::write(dest, blob, offset_map); |
394 | auto *inst = static_cast<impl_type *>(dest); |
395 | inst->ekey = ekey; |
396 | inst->fail_jump = calc_jump(offset_map, this, target); |
397 | } |
398 | |
399 | void RoseInstrCheckMinLength::write(void *dest, RoseEngineBlob &blob, |
400 | const OffsetMap &offset_map) const { |
401 | RoseInstrBase::write(dest, blob, offset_map); |
402 | auto *inst = static_cast<impl_type *>(dest); |
403 | inst->end_adj = end_adj; |
404 | inst->min_length = min_length; |
405 | inst->fail_jump = calc_jump(offset_map, this, target); |
406 | } |
407 | |
408 | void RoseInstrSetState::write(void *dest, RoseEngineBlob &blob, |
409 | const OffsetMap &offset_map) const { |
410 | RoseInstrBase::write(dest, blob, offset_map); |
411 | auto *inst = static_cast<impl_type *>(dest); |
412 | inst->index = index; |
413 | } |
414 | |
415 | void RoseInstrSetGroups::write(void *dest, RoseEngineBlob &blob, |
416 | const OffsetMap &offset_map) const { |
417 | RoseInstrBase::write(dest, blob, offset_map); |
418 | auto *inst = static_cast<impl_type *>(dest); |
419 | inst->groups = groups; |
420 | } |
421 | |
422 | void RoseInstrSquashGroups::write(void *dest, RoseEngineBlob &blob, |
423 | const OffsetMap &offset_map) const { |
424 | RoseInstrBase::write(dest, blob, offset_map); |
425 | auto *inst = static_cast<impl_type *>(dest); |
426 | inst->groups = groups; |
427 | } |
428 | |
429 | void RoseInstrCheckState::write(void *dest, RoseEngineBlob &blob, |
430 | const OffsetMap &offset_map) const { |
431 | RoseInstrBase::write(dest, blob, offset_map); |
432 | auto *inst = static_cast<impl_type *>(dest); |
433 | inst->index = index; |
434 | inst->fail_jump = calc_jump(offset_map, this, target); |
435 | } |
436 | |
437 | void RoseInstrSparseIterBegin::write(void *dest, RoseEngineBlob &blob, |
438 | const OffsetMap &offset_map) const { |
439 | RoseInstrBase::write(dest, blob, offset_map); |
440 | auto *inst = static_cast<impl_type *>(dest); |
441 | inst->fail_jump = calc_jump(offset_map, this, target); |
442 | |
443 | // Resolve and write the multibit sparse iterator and the jump table. |
444 | vector<u32> keys; |
445 | vector<u32> jump_offsets; |
446 | for (const auto &jump : jump_table) { |
447 | keys.push_back(jump.first); |
448 | assert(contains(offset_map, jump.second)); |
449 | jump_offsets.push_back(offset_map.at(jump.second)); |
450 | } |
451 | |
452 | auto iter = mmbBuildSparseIterator(keys, num_keys); |
453 | assert(!iter.empty()); |
454 | inst->iter_offset = blob.add_iterator(iter); |
455 | inst->jump_table = blob.add(jump_offsets.begin(), jump_offsets.end()); |
456 | |
457 | // Store offsets for corresponding SPARSE_ITER_NEXT operations. |
458 | is_written = true; |
459 | iter_offset = inst->iter_offset; |
460 | jump_table_offset = inst->jump_table; |
461 | } |
462 | |
463 | void RoseInstrSparseIterNext::write(void *dest, RoseEngineBlob &blob, |
464 | const OffsetMap &offset_map) const { |
465 | RoseInstrBase::write(dest, blob, offset_map); |
466 | auto *inst = static_cast<impl_type *>(dest); |
467 | inst->state = state; |
468 | inst->fail_jump = calc_jump(offset_map, this, target); |
469 | |
470 | // Use the same sparse iterator and jump table as the SPARSE_ITER_BEGIN |
471 | // instruction. |
472 | assert(begin); |
473 | assert(contains(offset_map, begin)); |
474 | assert(begin->is_written); |
475 | inst->iter_offset = begin->iter_offset; |
476 | inst->jump_table = begin->jump_table_offset; |
477 | } |
478 | |
479 | void RoseInstrSparseIterAny::write(void *dest, RoseEngineBlob &blob, |
480 | const OffsetMap &offset_map) const { |
481 | RoseInstrBase::write(dest, blob, offset_map); |
482 | auto *inst = static_cast<impl_type *>(dest); |
483 | inst->fail_jump = calc_jump(offset_map, this, target); |
484 | |
485 | // Write the multibit sparse iterator. |
486 | auto iter = mmbBuildSparseIterator(keys, num_keys); |
487 | assert(!iter.empty()); |
488 | inst->iter_offset = blob.add_iterator(iter); |
489 | } |
490 | |
491 | void RoseInstrEnginesEod::write(void *dest, RoseEngineBlob &blob, |
492 | const OffsetMap &offset_map) const { |
493 | RoseInstrBase::write(dest, blob, offset_map); |
494 | auto *inst = static_cast<impl_type *>(dest); |
495 | inst->iter_offset = iter_offset; |
496 | } |
497 | |
498 | void RoseInstrCheckLongLit::write(void *dest, RoseEngineBlob &blob, |
499 | const OffsetMap &offset_map) const { |
500 | RoseInstrBase::write(dest, blob, offset_map); |
501 | auto *inst = static_cast<impl_type *>(dest); |
502 | assert(!literal.empty()); |
503 | inst->lit_offset = blob.add(literal.c_str(), literal.size(), 1); |
504 | inst->lit_length = verify_u32(literal.size()); |
505 | inst->fail_jump = calc_jump(offset_map, this, target); |
506 | } |
507 | |
508 | void RoseInstrCheckLongLitNocase::write(void *dest, RoseEngineBlob &blob, |
509 | const OffsetMap &offset_map) const { |
510 | RoseInstrBase::write(dest, blob, offset_map); |
511 | auto *inst = static_cast<impl_type *>(dest); |
512 | assert(!literal.empty()); |
513 | inst->lit_offset = blob.add(literal.c_str(), literal.size(), 1); |
514 | inst->lit_length = verify_u32(literal.size()); |
515 | inst->fail_jump = calc_jump(offset_map, this, target); |
516 | } |
517 | |
518 | void RoseInstrCheckMedLit::write(void *dest, RoseEngineBlob &blob, |
519 | const OffsetMap &offset_map) const { |
520 | RoseInstrBase::write(dest, blob, offset_map); |
521 | auto *inst = static_cast<impl_type *>(dest); |
522 | assert(!literal.empty()); |
523 | inst->lit_offset = blob.add(literal.c_str(), literal.size(), 1); |
524 | inst->lit_length = verify_u32(literal.size()); |
525 | inst->fail_jump = calc_jump(offset_map, this, target); |
526 | } |
527 | |
528 | void RoseInstrCheckMedLitNocase::write(void *dest, RoseEngineBlob &blob, |
529 | const OffsetMap &offset_map) const { |
530 | RoseInstrBase::write(dest, blob, offset_map); |
531 | auto *inst = static_cast<impl_type *>(dest); |
532 | assert(!literal.empty()); |
533 | inst->lit_offset = blob.add(literal.c_str(), literal.size(), 1); |
534 | inst->lit_length = verify_u32(literal.size()); |
535 | inst->fail_jump = calc_jump(offset_map, this, target); |
536 | } |
537 | |
538 | void RoseInstrMultipathLookaround::write(void *dest, RoseEngineBlob &blob, |
539 | const OffsetMap &offset_map) const { |
540 | RoseInstrBase::write(dest, blob, offset_map); |
541 | auto *inst = static_cast<impl_type *>(dest); |
542 | auto &cache = blob.lookaround_cache; |
543 | vector<s8> look_offsets; |
544 | vector<vector<CharReach>> reaches; |
545 | for (const auto &vle : multi_look) { |
546 | reaches.push_back({}); |
547 | bool done_offset = false; |
548 | |
549 | for (const auto &le : vle) { |
550 | reaches.back().push_back(le.reach); |
551 | |
552 | /* empty reaches don't have valid offsets */ |
553 | if (!done_offset && le.reach.any()) { |
554 | look_offsets.push_back(le.offset); |
555 | done_offset = true; |
556 | } |
557 | } |
558 | } |
559 | inst->look_index = cache.get_offset_of(look_offsets, blob); |
560 | inst->reach_index = cache.get_offset_of(reaches, blob); |
561 | inst->count = verify_u32(multi_look.size()); |
562 | inst->last_start = last_start; |
563 | copy(begin(start_mask), end(start_mask), inst->start_mask); |
564 | inst->fail_jump = calc_jump(offset_map, this, target); |
565 | } |
566 | |
567 | void RoseInstrCheckMultipathShufti16x8::write(void *dest, RoseEngineBlob &blob, |
568 | const OffsetMap &offset_map) const { |
569 | RoseInstrBase::write(dest, blob, offset_map); |
570 | auto *inst = static_cast<impl_type *>(dest); |
571 | copy(begin(nib_mask), end(nib_mask), inst->nib_mask); |
572 | copy(begin(bucket_select_mask), begin(bucket_select_mask) + 16, |
573 | inst->bucket_select_mask); |
574 | copy(begin(data_select_mask), begin(data_select_mask) + 16, |
575 | inst->data_select_mask); |
576 | inst->hi_bits_mask = hi_bits_mask; |
577 | inst->lo_bits_mask = lo_bits_mask; |
578 | inst->neg_mask = neg_mask; |
579 | inst->base_offset = base_offset; |
580 | inst->last_start = last_start; |
581 | inst->fail_jump = calc_jump(offset_map, this, target); |
582 | } |
583 | |
584 | void RoseInstrCheckMultipathShufti32x8::write(void *dest, RoseEngineBlob &blob, |
585 | const OffsetMap &offset_map) const { |
586 | RoseInstrBase::write(dest, blob, offset_map); |
587 | auto *inst = static_cast<impl_type *>(dest); |
588 | copy(begin(hi_mask), begin(hi_mask) + 16, inst->hi_mask); |
589 | copy(begin(lo_mask), begin(lo_mask) + 16, inst->lo_mask); |
590 | copy(begin(bucket_select_mask), begin(bucket_select_mask) + 32, |
591 | inst->bucket_select_mask); |
592 | copy(begin(data_select_mask), begin(data_select_mask) + 32, |
593 | inst->data_select_mask); |
594 | inst->hi_bits_mask = hi_bits_mask; |
595 | inst->lo_bits_mask = lo_bits_mask; |
596 | inst->neg_mask = neg_mask; |
597 | inst->base_offset = base_offset; |
598 | inst->last_start = last_start; |
599 | inst->fail_jump = calc_jump(offset_map, this, target); |
600 | } |
601 | |
602 | void RoseInstrCheckMultipathShufti32x16::write(void *dest, RoseEngineBlob &blob, |
603 | const OffsetMap &offset_map) const { |
604 | RoseInstrBase::write(dest, blob, offset_map); |
605 | auto *inst = static_cast<impl_type *>(dest); |
606 | copy(begin(hi_mask), end(hi_mask), inst->hi_mask); |
607 | copy(begin(lo_mask), end(lo_mask), inst->lo_mask); |
608 | copy(begin(bucket_select_mask_hi), begin(bucket_select_mask_hi) + 32, |
609 | inst->bucket_select_mask_hi); |
610 | copy(begin(bucket_select_mask_lo), begin(bucket_select_mask_lo) + 32, |
611 | inst->bucket_select_mask_lo); |
612 | copy(begin(data_select_mask), begin(data_select_mask) + 32, |
613 | inst->data_select_mask); |
614 | inst->hi_bits_mask = hi_bits_mask; |
615 | inst->lo_bits_mask = lo_bits_mask; |
616 | inst->neg_mask = neg_mask; |
617 | inst->base_offset = base_offset; |
618 | inst->last_start = last_start; |
619 | inst->fail_jump = calc_jump(offset_map, this, target); |
620 | } |
621 | |
622 | void RoseInstrCheckMultipathShufti64::write(void *dest, RoseEngineBlob &blob, |
623 | const OffsetMap &offset_map) const { |
624 | RoseInstrBase::write(dest, blob, offset_map); |
625 | auto *inst = static_cast<impl_type *>(dest); |
626 | copy(begin(hi_mask), begin(hi_mask) + 16, inst->hi_mask); |
627 | copy(begin(lo_mask), begin(lo_mask) + 16, inst->lo_mask); |
628 | copy(begin(bucket_select_mask), end(bucket_select_mask), |
629 | inst->bucket_select_mask); |
630 | copy(begin(data_select_mask), end(data_select_mask), |
631 | inst->data_select_mask); |
632 | inst->hi_bits_mask = hi_bits_mask; |
633 | inst->lo_bits_mask = lo_bits_mask; |
634 | inst->neg_mask = neg_mask; |
635 | inst->base_offset = base_offset; |
636 | inst->last_start = last_start; |
637 | inst->fail_jump = calc_jump(offset_map, this, target); |
638 | } |
639 | |
640 | void RoseInstrIncludedJump::write(void *dest, RoseEngineBlob &blob, |
641 | const OffsetMap &offset_map) const { |
642 | RoseInstrBase::write(dest, blob, offset_map); |
643 | auto *inst = static_cast<impl_type *>(dest); |
644 | inst->child_offset = child_offset; |
645 | inst->squash = squash; |
646 | } |
647 | |
648 | void RoseInstrSetLogical::write(void *dest, RoseEngineBlob &blob, |
649 | const OffsetMap &offset_map) const { |
650 | RoseInstrBase::write(dest, blob, offset_map); |
651 | auto *inst = static_cast<impl_type *>(dest); |
652 | inst->lkey = lkey; |
653 | inst->offset_adjust = offset_adjust; |
654 | } |
655 | |
656 | void RoseInstrSetCombination::write(void *dest, RoseEngineBlob &blob, |
657 | const OffsetMap &offset_map) const { |
658 | RoseInstrBase::write(dest, blob, offset_map); |
659 | auto *inst = static_cast<impl_type *>(dest); |
660 | inst->ckey = ckey; |
661 | } |
662 | |
663 | void RoseInstrSetExhaust::write(void *dest, RoseEngineBlob &blob, |
664 | const OffsetMap &offset_map) const { |
665 | RoseInstrBase::write(dest, blob, offset_map); |
666 | auto *inst = static_cast<impl_type *>(dest); |
667 | inst->ekey = ekey; |
668 | } |
669 | |
670 | } |
671 | |