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

Last change on this file since 5670 was 5620, checked in by nmedfort, 23 months 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.