source: icGREP/icgrep-devel/icgrep/UCD/ucd_compiler.cpp @ 5671

Last change on this file since 5671 was 5620, checked in by nmedfort, 2 years ago

Bug fixes for multigrep mode. Optional PabloKernel? branch hit counter added. Minor optimizations.

File size: 23.9 KB
Line 
1#include "ucd_compiler.hpp"
2#include <cc/cc_compiler.h>
3#include <UCD/unicode_set.h>
4#include <re/re_name.h>
5#include <utf8_encoder.h>
6#include <utf16_encoder.h>
7#include <array>
8#include <pablo/pe_var.h>
9#include <pablo/pe_zeroes.h>
10#include <pablo/pe_ones.h>
11
12#include <pablo/printer_pablos.h>
13#include <llvm/Support/raw_ostream.h>
14
15using namespace cc;
16using namespace re;
17using namespace pablo;
18using namespace llvm;
19using namespace boost::container;
20
21namespace UCD {
22
23/** ------------------------------------------------------------------------------------------------------------- *
24 * @brief UTF_16 UTF_8
25 ** ------------------------------------------------------------------------------------------------------------- */
26inline codepoint_t encodingByte(const codepoint_t cp, const unsigned n, bool UTF_16) {
27    return UTF_16 ? UTF16_Encoder::encodingByte(cp, n) : UTF8_Encoder::encodingByte(cp, n);
28}
29
30inline unsigned length(const codepoint_t cp, bool UTF_16) {
31    return UTF_16 ? UTF16_Encoder::length(cp) : UTF8_Encoder::length(cp);
32}
33
34inline codepoint_t maxCodePoint(const unsigned length, bool UTF_16) {
35    return UTF_16 ?  UTF16_Encoder::maxCodePoint(length) : UTF8_Encoder::maxCodePoint(length);
36}
37
38inline bool isLowCodePointAfterByte(const codepoint_t cp, const unsigned n, bool UTF_16) {
39    return UTF_16 ? UTF16_Encoder::isLowCodePointAfterByte(cp, n) : UTF8_Encoder::isLowCodePointAfterByte(cp, n);
40}
41inline bool isHighCodePointAfterByte(const codepoint_t cp, const unsigned n, bool UTF_16) {
42    return UTF_16 ? UTF16_Encoder::isHighCodePointAfterByte(cp, n) : UTF8_Encoder::isHighCodePointAfterByte(cp, n);
43}
44inline codepoint_t minCodePointWithCommonBytes(const re::codepoint_t cp, const unsigned n, bool UTF_16) {
45    return UTF_16 ? UTF16_Encoder::minCodePointWithCommonBytes(cp, n) : UTF8_Encoder::minCodePointWithCommonBytes(cp, n);
46}
47inline codepoint_t maxCodePointWithCommonBytes(const re::codepoint_t cp, const unsigned n, bool UTF_16) {
48    return UTF_16 ? UTF16_Encoder::maxCodePointWithCommonBytes(cp, n) : UTF8_Encoder::maxCodePointWithCommonBytes(cp, n);
49}
50
51const UCDCompiler::RangeList UCDCompiler::defaultIfHierachy = {
52    // Non-ASCII
53    {0x80, 0x10FFFF},
54    // Two-byte sequences
55    {0x80, 0x7FF},
56    {0x100, 0x3FF},
57    // 0100..017F; Latin Extended-A
58    // 0180..024F; Latin Extended-B
59    // 0250..02AF; IPA Extensions
60    // 02B0..02FF; Spacing Modifier Letters
61    {0x100, 0x2FF}, {0x100, 0x24F}, {0x100, 0x17F}, {0x180, 0x24F}, {0x250, 0x2AF}, {0x2B0, 0x2FF},
62    // 0300..036F; Combining Diacritical Marks
63    // 0370..03FF; Greek and Coptic
64    {0x300, 0x36F}, {0x370, 0x3FF},
65    // 0400..04FF; Cyrillic
66    // 0500..052F; Cyrillic Supplement
67    // 0530..058F; Armenian
68    // 0590..05FF; Hebrew
69    // 0600..06FF; Arabic
70    {0x400, 0x5FF}, {0x400, 0x4FF}, {0x500, 0x058F}, {0x500, 0x52F}, {0x530, 0x58F}, {0x590, 0x5FF}, {0x600, 0x6FF},
71    // 0700..074F; Syriac
72    // 0750..077F; Arabic Supplement
73    // 0780..07BF; Thaana
74    // 07C0..07FF; NKo
75    {0x700, 0x77F}, {0x700, 0x74F}, {0x750, 0x77F}, {0x780, 0x7FF}, {0x780, 0x7BF}, {0x7C0, 0x7FF},
76    // Three-byte sequences
77    {0x800, 0xFFFF}, {0x800, 0x4DFF}, {0x800, 0x1FFF}, {0x800, 0x0FFF},
78    // 0800..083F; Samaritan
79    // 0840..085F; Mandaic
80    // 08A0..08FF; Arabic Extended-A
81    // 0900..097F; Devanagari
82    // 0980..09FF; Bengali
83    // 0A00..0A7F; Gurmukhi
84    // 0A80..0AFF; Gujarati
85    // 0B00..0B7F; Oriya
86    // 0B80..0BFF; Tamil
87    // 0C00..0C7F; Telugu
88    // 0C80..0CFF; Kannada
89    // 0D00..0D7F; Malayalam
90    // 0D80..0DFF; Sinhala
91    // 0E00..0E7F; Thai
92    // 0E80..0EFF; Lao
93    // 0F00..0FFF; Tibetan
94    {0x1000, 0x1FFF},
95    // 1000..109F; Myanmar
96    // 10A0..10FF; Georgian
97    // 1100..11FF; Hangul Jamo
98    // 1200..137F; Ethiopic
99    // 1380..139F; Ethiopic Supplement
100    // 13A0..13FF; Cherokee
101    // 1400..167F; Unified Canadian Aboriginal Syllabics
102    // 1680..169F; Ogham
103    // 16A0..16FF; Runic
104    // 1700..171F; Tagalog
105    // 1720..173F; Hanunoo
106    // 1740..175F; Buhid
107    // 1760..177F; Tagbanwa
108    // 1780..17FF; Khmer
109    // 1800..18AF; Mongolian
110    // 18B0..18FF; Unified Canadian Aboriginal Syllabics Extended
111    // 1900..194F; Limbu
112    // 1950..197F; Tai Le
113    // 1980..19DF; New Tai Lue
114    // 19E0..19FF; Khmer Symbols
115    // 1A00..1A1F; Buginese
116    // 1A20..1AAF; Tai Tham
117    // 1AB0..1AFF; Combining Diacritical Marks Extended
118    // 1B00..1B7F; Balinese
119    // 1B80..1BBF; Sundanese
120    // 1BC0..1BFF; Batak
121    // 1C00..1C4F; Lepcha
122    // 1C50..1C7F; Ol Chiki
123    // 1CC0..1CCF; Sundanese Supplement
124    // 1CD0..1CFF; Vedic Extensions
125    // 1D00..1D7F; Phonetic Extensions
126    // 1D80..1DBF; Phonetic Extensions Supplement
127    // 1DC0..1DFF; Combining Diacritical Marks Supplement
128    // 1E00..1EFF; Latin Extended Additional
129    // 1F00..1FFF; Greek Extended
130    {0x2000, 0x4DFF}, {0x2000, 0x2FFF},
131    {0x3000, 0x4DFF},
132    {0x4E00, 0x9FFF},
133    // 4E00..9FFF; CJK Unified Ideographs
134    {0xA000, 0xFFFF},
135
136    {0x10000, 0x10FFFF}};
137
138const UCDCompiler::RangeList UCDCompiler::noIfHierachy = {{0x80, 0x10FFFF}};
139
140/** ------------------------------------------------------------------------------------------------------------- *
141 * @brief generateRange
142 ** ------------------------------------------------------------------------------------------------------------- */
143void UCDCompiler::generateRange(const RangeList & ifRanges, PabloBuilder & entry) {
144    // Pregenerate the suffix var outside of the if ranges. The DCE pass will either eliminate it if it's not used or the
145    // code sinking pass will move appropriately into an inner if block.
146    CC *  suffix = makeCC(0x80, 0xBF);
147    assert (!suffix->empty());
148    mSuffixVar = mCharacterClassCompiler.compileCC(suffix, entry);
149    generateRange(ifRanges, 0, UNICODE_MAX, entry);
150}
151
152/** ------------------------------------------------------------------------------------------------------------- *
153 * @brief generateRange
154 * @param ifRangeList
155 ** ------------------------------------------------------------------------------------------------------------- */
156void UCDCompiler::generateRange(const RangeList & ifRanges, const codepoint_t lo, const codepoint_t hi, PabloBuilder & builder) {
157
158    // Codepoints in unenclosed ranges will be computed unconditionally.
159    // Generate them first so that computed subexpressions may be shared
160    // with calculations within the if hierarchy.
161    const auto enclosed = rangeIntersect(ifRanges, lo, hi);
162    for (const auto rg : rangeGaps(enclosed, lo, hi)) {
163        generateSubRanges(lo_codepoint(rg), hi_codepoint(rg), builder);
164    }
165
166    for (auto & f : mTargetValue) {
167        const auto v = mTarget.find(f.first);
168        assert (v != mTarget.end());
169        PabloAST * value = f.second;
170        if (!isa<Zeroes>(value)) {
171            if (LLVM_LIKELY(builder.getParent() != nullptr)) {
172                value = builder.createOr(v->second, value);
173            }
174            builder.createAssign(v->second, value);
175            f.second = builder.createZeroes();
176        }
177    }
178
179    const auto outer = outerRanges(enclosed);
180    const auto inner = innerRanges(enclosed);
181
182    Values nonIntersectingTargets;
183
184    for (const auto range : outer) {
185
186        // Split our current target list into two sets: the intersecting and non-intersecting ones. Any non-
187        // intersecting set will be removed from the current map to eliminate the possibility of it being
188        // considered until after we leave the current range. The intersecting sets are also stored to ensure
189        // that we know what the original target value was going into this range block so tha we can OR the
190        // inner value with the outer value.
191
192        for (auto f = mTargetValue.begin(); f != mTargetValue.end(); ) {
193            if (f->first->intersects(range.first, range.second)) {
194                ++f;
195            } else {
196                nonIntersectingTargets.push_back(*f);
197                f = mTargetValue.erase(f);
198            }
199        }
200        if (mTargetValue.size() > 0) {
201            PabloBuilder inner_block = PabloBuilder::Create(builder);
202            builder.createIf(ifTestCompiler(range.first, range.second, builder), inner_block);
203            generateRange(inner, range.first, range.second, inner_block);
204        }
205        for (auto t : nonIntersectingTargets) {
206            mTargetValue.insert(t);
207        }
208        nonIntersectingTargets.clear();
209    }
210}
211
212/** ------------------------------------------------------------------------------------------------------------- *
213 * @brief generateSubRanges
214 ** ------------------------------------------------------------------------------------------------------------- */
215void UCDCompiler::generateSubRanges(const codepoint_t lo, const codepoint_t hi, PabloBuilder & builder) {
216    for (auto & t : mTargetValue) {
217        const auto range = rangeIntersect(*t.first, lo, hi);
218        PabloAST * target = t.second;
219        // Divide by UTF-8 length, separating out E0, ED, F0 and F4 ranges
220        const std::array<interval_t, 9> ranges =
221            {{{0, 0x7F}, {0x80, 0x7FF}, {0x800, 0xFFF}, {0x1000, 0xD7FF}, {0xD800, 0xDFFF},
222             {0xE000, 0xFFFF}, {0x10000, 0x3FFFF}, {0x40000, 0xFFFFF}, {0x100000, 0x10FFFF}}};
223        for (auto r : ranges) {
224            const auto subrange = rangeIntersect(range, lo_codepoint(r), hi_codepoint(r));
225            target = sequenceGenerator(std::move(subrange), 1, builder, target, nullptr);
226        }
227        t.second = target;
228    }
229}
230
231/** ------------------------------------------------------------------------------------------------------------- *
232 * @brief sequenceGenerator
233 * @param ifRangeList
234 *
235 *
236 * Generate remaining code to match UTF-8 code sequences within the codepoint set cpset, assuming that the code
237 * matching the sequences up to byte number byte_no have been generated.
238 ** ------------------------------------------------------------------------------------------------------------- */
239PabloAST * UCDCompiler::sequenceGenerator(const RangeList && ranges, const unsigned byte_no, PabloBuilder & builder, PabloAST * target, PabloAST * prefix) {
240        bool isUTF_16 = mCharacterClassCompiler.isUTF_16();
241
242    if (LLVM_LIKELY(ranges.size() > 0)) {
243
244        codepoint_t lo, hi;
245        std::tie(lo, hi) = ranges[0];
246
247        const auto min = length(lo_codepoint(ranges.front()), isUTF_16);
248        const auto max = length(hi_codepoint(ranges.back()), isUTF_16);
249
250        if (min != max) {
251            const auto mid = maxCodePoint(min, isUTF_16);
252            target = sequenceGenerator(std::move(rangeIntersect(ranges, lo, mid)), byte_no, builder, target, prefix);
253            target = sequenceGenerator(std::move(rangeIntersect(ranges, mid + 1, hi)), byte_no, builder, target, prefix);
254        } else if (min == byte_no) {
255            // We have a single byte remaining to match for all code points in this CC.
256            // Use the byte class compiler to generate matches for these codepoints.
257            PabloAST * var = mCharacterClassCompiler.compileCC(makeCC(byteDefinitions(ranges, byte_no, isUTF_16)), builder);
258            if (byte_no > 1) {
259                var = builder.createAnd(var, builder.createAdvance(makePrefix(lo, byte_no, builder, prefix), 1));
260            }
261            target = builder.createOr(target, var);
262        } else {
263            for (auto rg : ranges) {
264                codepoint_t lo, hi;
265                std::tie(lo, hi) = rg;
266                const auto lo_byte = encodingByte(lo, byte_no, isUTF_16);
267                const auto hi_byte = encodingByte(hi, byte_no, isUTF_16);
268                if (lo_byte != hi_byte) {
269                    unsigned num = isUTF_16 ? 10 : 6;
270                    if (!isLowCodePointAfterByte(lo, byte_no, isUTF_16)) {
271                        const codepoint_t mid = lo | ((1 << (num * (min - byte_no))) - 1);
272                        target = sequenceGenerator(lo, mid, byte_no, builder, target, prefix);
273                        target = sequenceGenerator(mid + 1, hi, byte_no, builder, target, prefix);
274                    } else if (!isHighCodePointAfterByte(hi, byte_no, isUTF_16)) {
275                        const codepoint_t mid = hi & ~((1 << (num * (min - byte_no))) - 1);
276                        target = sequenceGenerator(lo, mid - 1, byte_no, builder, target, prefix);
277                        target = sequenceGenerator(mid, hi, byte_no, builder, target, prefix);
278                    } else { // we have a prefix group of type (a)
279                        PabloAST * var = mCharacterClassCompiler.compileCC(makeCC(lo_byte, hi_byte), builder);
280                        if (byte_no > 1) {
281                            var = builder.createAnd(builder.createAdvance(prefix, 1), var);
282                        }
283                        for (unsigned i = byte_no; i != length(lo, isUTF_16); ++i) {
284                            var = builder.createAnd(mSuffixVar, builder.createAdvance(var, 1));
285                        }
286                        target = builder.createOr(target, var);
287                    }
288                } else { // lbyte == hbyte
289                    PabloAST * var = mCharacterClassCompiler.compileCC(makeCC(lo_byte, hi_byte), builder);
290                    if (byte_no > 1) {
291                        var = builder.createAnd(builder.createAdvance(prefix ? prefix : var, 1), var);
292                    }
293                    if (byte_no < length(lo, isUTF_16)) {
294                        target = sequenceGenerator(lo, hi, byte_no + 1, builder, target, var);
295                    }
296                }
297            }
298        }
299    }
300    return target;
301}
302
303/** ------------------------------------------------------------------------------------------------------------- *
304 * @brief sequenceGenerator
305 ** ------------------------------------------------------------------------------------------------------------- */
306inline PabloAST * UCDCompiler::sequenceGenerator(const codepoint_t lo, const codepoint_t hi, const unsigned byte_no, PabloBuilder & builder, PabloAST * target, PabloAST * prefix) {
307    return sequenceGenerator({{ lo, hi }}, byte_no, builder, target, prefix);
308}
309
310/** ------------------------------------------------------------------------------------------------------------- *
311 * @brief ifTestCompiler
312 ** ------------------------------------------------------------------------------------------------------------- */
313inline PabloAST * UCDCompiler::ifTestCompiler(const codepoint_t lo, const codepoint_t hi, PabloBuilder & builder) {
314    return ifTestCompiler(lo, hi, 1, builder, builder.createOnes());
315}
316
317/** ------------------------------------------------------------------------------------------------------------- *
318 * @brief ifTestCompiler
319 ** ------------------------------------------------------------------------------------------------------------- */
320PabloAST * UCDCompiler::ifTestCompiler(const codepoint_t lo, const codepoint_t hi, const unsigned byte_no, PabloBuilder & builder, PabloAST * target) {
321
322        bool isUTF_16 = mCharacterClassCompiler.isUTF_16();
323    codepoint_t lo_byte = encodingByte(lo, byte_no, isUTF_16);
324    codepoint_t hi_byte = encodingByte(hi, byte_no, isUTF_16);
325    const bool at_lo_boundary = (lo == 0 || encodingByte(lo - 1, byte_no, isUTF_16) != lo_byte);
326    const bool at_hi_boundary = (hi == 0x10FFFF || encodingByte(hi + 1, byte_no, isUTF_16) != hi_byte);
327
328    if (at_lo_boundary && at_hi_boundary) {
329        if (!isUTF_16) {
330            if (lo_byte != hi_byte) {
331                if (lo == 0x80) lo_byte = 0xC0;
332                if (hi == 0x10FFFF) hi_byte = 0xFF;
333            }
334        }
335        PabloAST * cc = mCharacterClassCompiler.compileCC(makeCC(lo_byte, hi_byte), builder);
336        target = builder.createAnd(cc, target);
337    } else if (lo_byte == hi_byte) {
338        PabloAST * cc = mCharacterClassCompiler.compileCC(makeCC(lo_byte, hi_byte), builder);
339        target = builder.createAnd(cc, target);
340        target = builder.createAdvance(target, 1);
341        target = ifTestCompiler(lo, hi, byte_no + 1, builder, target);
342    } else if (!at_hi_boundary) {
343        const auto mid = minCodePointWithCommonBytes(hi, byte_no, isUTF_16);
344        PabloAST * e1 = ifTestCompiler(lo, mid - 1, byte_no, builder, target);
345        PabloAST * e2 = ifTestCompiler(mid, hi, byte_no, builder, target);
346        target = builder.createOr(e1, e2);
347    } else {
348        const auto mid = maxCodePointWithCommonBytes(lo, byte_no, isUTF_16);
349        PabloAST * e1 = ifTestCompiler(lo, mid, byte_no, builder, target);
350        PabloAST * e2 = ifTestCompiler(mid + 1, hi, byte_no, builder, target);
351        target = builder.createOr(e1, e2);
352    }
353    return target;
354}
355
356/** ------------------------------------------------------------------------------------------------------------- *
357 * @brief definePrecedingPrefix
358 * @param ifRangeList
359 *
360 *
361 * Ensure the sequence of preceding bytes is defined, up to, but not including the given byte_no
362 ** ------------------------------------------------------------------------------------------------------------- */
363PabloAST * UCDCompiler::makePrefix(const codepoint_t cp, const unsigned byte_no, PabloBuilder & builder, PabloAST * prefix) {
364    assert (byte_no >= 1 && byte_no <= 4);
365    assert (byte_no == 1 || prefix != nullptr);
366    bool isUTF_16 = mCharacterClassCompiler.isUTF_16();
367    for (unsigned i = 1; i != byte_no; ++i) {
368        const CC * const cc = makeCC(encodingByte(cp, i, isUTF_16));
369        PabloAST * var = mCharacterClassCompiler.compileCC(cc, builder);
370        if (i > 1) {
371            var = builder.createAnd(var, builder.createAdvance(prefix, 1));
372        }
373        prefix = var;
374    }
375    return prefix;
376}
377
378/** ------------------------------------------------------------------------------------------------------------- *
379 * @brief definePrecedingPrefix
380 * @param ifRangeList
381 *
382 *
383 * Ensure the sequence of preceding bytes is defined, up to, but not including the given byte_no
384 ** ------------------------------------------------------------------------------------------------------------- */
385UCDCompiler::RangeList UCDCompiler::byteDefinitions(const RangeList & list, const unsigned byte_no, bool isUTF_16) {
386    RangeList result;
387    result.reserve(list.size());
388    for (const auto & i : list) {
389        result.emplace_back(encodingByte(lo_codepoint(i), byte_no, isUTF_16), encodingByte(hi_codepoint(i), byte_no, isUTF_16));
390    }
391    return result;
392}
393
394/** ------------------------------------------------------------------------------------------------------------- *
395 * @brief rangeIntersect
396 * @param list
397 * @param lo
398 * @param hi
399 ** ------------------------------------------------------------------------------------------------------------- */
400template <typename RangeListOrUnicodeSet>
401UCDCompiler::RangeList UCDCompiler::rangeIntersect(const RangeListOrUnicodeSet & list, const codepoint_t lo, const codepoint_t hi) {
402    RangeList result;
403    for (const auto i : list) {
404        if ((lo_codepoint(i) <= hi) && (hi_codepoint(i) >= lo)) {
405            result.emplace_back(std::max(lo, lo_codepoint(i)), std::min(hi, hi_codepoint(i)));
406        }
407    }
408    return result;
409}
410
411/** ------------------------------------------------------------------------------------------------------------- *
412 * @brief rangeGaps
413 * @param cc
414 * @param lo
415 * @param hi
416 ** ------------------------------------------------------------------------------------------------------------- */
417UCDCompiler::RangeList UCDCompiler::rangeGaps(const RangeList & list, const codepoint_t lo, const codepoint_t hi) {
418    RangeList gaps;
419    if (LLVM_LIKELY(lo < hi)) {
420        if (LLVM_UNLIKELY(list.empty())) {
421            gaps.emplace_back(lo, hi);
422        } else {
423            codepoint_t cp = lo;
424            for (const auto & i : list) {
425                if (hi_codepoint(i) < cp) {
426                    continue;
427                } else if (lo_codepoint(i) > cp) {
428                    gaps.emplace_back(cp, lo_codepoint(i) - 1);
429                } else if (hi_codepoint(i) >= hi) {
430                    continue;
431                }
432                cp = hi_codepoint(i) + 1;
433            }
434        }
435    }
436    return gaps;
437}
438
439/** ------------------------------------------------------------------------------------------------------------- *
440 * @brief outerRanges
441 * @param list
442 ** ------------------------------------------------------------------------------------------------------------- */
443UCDCompiler::RangeList UCDCompiler::outerRanges(const RangeList & list) {
444    RangeList ranges;
445    if (LLVM_LIKELY(list.size() > 0)) {
446        auto i = list.cbegin();
447        for (auto j = i + 1; j != list.cend(); ++j) {
448            if (hi_codepoint(*j) > hi_codepoint(*i)) {
449                ranges.emplace_back(lo_codepoint(*i), hi_codepoint(*i));
450                i = j;
451            }
452        }
453        if (LLVM_LIKELY(i != list.end())) {
454            ranges.emplace_back(lo_codepoint(*i), hi_codepoint(*i));
455        }
456    }
457    return ranges;
458}
459
460/** ------------------------------------------------------------------------------------------------------------- *
461 * @brief innerRanges
462 ** ------------------------------------------------------------------------------------------------------------- */
463UCDCompiler::RangeList UCDCompiler::innerRanges(const RangeList & list) {
464    RangeList ranges;
465    if (LLVM_LIKELY(list.size() > 0)) {
466        for (auto i = list.cbegin(), j = i + 1; j != list.cend(); ++j) {
467            if (hi_codepoint(*j) <= hi_codepoint(*i)) {
468                ranges.emplace_back(lo_codepoint(*j), hi_codepoint(*j));
469            } else {
470                i = j;
471            }
472        }
473    }
474    return ranges;
475}
476
477/** ------------------------------------------------------------------------------------------------------------- *
478 * @brief generateWithDefaultIfHierarchy
479 ** ------------------------------------------------------------------------------------------------------------- */
480void UCDCompiler::generateWithDefaultIfHierarchy(NameMap & names, PabloBuilder & entry) {
481    makeTargets(entry, names);
482    generateRange(defaultIfHierachy, entry);
483}
484
485/** ------------------------------------------------------------------------------------------------------------- *
486 * @brief generateWithoutIfHierarchy
487 ** ------------------------------------------------------------------------------------------------------------- */
488void UCDCompiler::generateWithoutIfHierarchy(NameMap & names, PabloBuilder & entry) {
489    makeTargets(entry, names);
490    generateRange(noIfHierachy, entry);
491}
492
493/** ------------------------------------------------------------------------------------------------------------- *
494 * @brief addTargets
495 ** ------------------------------------------------------------------------------------------------------------- */
496inline void UCDCompiler::makeTargets(PabloBuilder & entry, NameMap & names) {
497
498    mTargetValue.clear();
499    mTarget.clear();
500
501    struct Comparator {
502        inline bool operator() (const CC * lh, const CC * rh) const{
503            return *lh < *rh;
504        }
505    } ec;
506
507    flat_map<CC *, Var *, Comparator> CCs(ec);
508
509    Zeroes * const zeroes = entry.createZeroes();
510
511    for (auto & t : names) {
512        Name * const name = t.first;
513        if (name->getType() == Name::Type::Byte) {
514            continue;
515        }       
516        CC * const cc = dyn_cast<CC>(name->getDefinition());
517        if (cc) {
518            const auto f = CCs.find(cc);
519            // This check may not be needed. Memoization ought to detect duplicate classes earlier.
520            if (LLVM_LIKELY(f == CCs.end())) {
521                PabloAST * const value = t.second ? t.second : zeroes;
522                mTargetValue.emplace(cc, value);
523                Var * const var = entry.createVar(name->getName(), value);
524                mTarget.emplace(cc, var);
525                CCs.emplace(cc, var);
526                t.second = var;
527            } else {
528                t.second = f->second;
529            }
530        } else {
531            report_fatal_error(name->getName() + " is not defined by a CC!");
532        }
533    }
534}
535
536/** ------------------------------------------------------------------------------------------------------------- *
537 * @brief constructor
538 ** ------------------------------------------------------------------------------------------------------------- */
539UCDCompiler::UCDCompiler(cc::CC_Compiler & ccCompiler)
540: mCharacterClassCompiler(ccCompiler)
541, mSuffixVar(nullptr) { }
542
543}
Note: See TracBrowser for help on using the repository browser.