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

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