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

Last change on this file since 5765 was 5748, checked in by nmedfort, 20 months ago

Bug fix for segment pipeline parallel mode + memory management improvements.

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