source: icGREP/icgrep-devel/icgrep/grep_engine.cpp @ 5489

Last change on this file since 5489 was 5489, checked in by nmedfort, 22 months ago

Bug fix for memory check and issues found parsing internal 'files'. Added backtrace option from execinfo.h

File size: 26.7 KB
Line 
1/*
2 *  Copyright (c) 2017 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include "grep_engine.h"
8#include "grep_interface.h"
9#include <llvm/IR/Module.h>
10#include <boost/filesystem.hpp>
11#include <UCD/UnicodeNameData.h>
12#include <UCD/resolve_properties.h>
13#include <kernels/cc_kernel.h>
14#include <kernels/grep_kernel.h>
15#include <kernels/linebreak_kernel.h>
16#include <kernels/streams_merge.h>
17#include <kernels/match_count.h>
18#include <kernels/source_kernel.h>
19#include <kernels/s2p_kernel.h>
20#include <kernels/scanmatchgen.h>
21#include <kernels/streamset.h>
22#include <kernels/until_n.h>
23#include <kernels/kernel_builder.h>
24#include <pablo/pablo_kernel.h>
25#include <re/re_cc.h>
26#include <re/re_toolchain.h>
27#include <toolchain/toolchain.h>
28#include <toolchain/cpudriver.h>
29#include <toolchain/NVPTXDriver.h>
30#include <iostream>
31#include <sstream>
32#include <cc/multiplex_CCs.h>
33#include <llvm/Support/raw_ostream.h>
34#include <util/aligned_allocator.h>
35#include <sys/stat.h>
36#include <fcntl.h>
37#include <errno.h>
38#include <mutex>
39
40#ifdef CUDA_ENABLED
41#include <preprocess.cpp>
42#include <IR_Gen/CudaDriver.h>
43#endif
44
45using namespace parabix;
46using namespace llvm;
47
48namespace grep {
49
50static std::stringstream * resultStrs = nullptr;
51static std::vector<std::string> inputFiles;
52static std::vector<std::string> linePrefix;
53static bool grepMatchFound;
54
55size_t * startPoints = nullptr;
56size_t * accumBytes = nullptr;
57
58
59std::mutex count_mutex;
60size_t fileCount;
61
62// DoGrep thread function.
63void *DoGrepThreadFunction(void *args)
64{
65    size_t fileIdx;
66    grep::GrepEngine * grepEngine = (grep::GrepEngine *)args;
67
68    count_mutex.lock();
69    fileIdx = fileCount;
70    fileCount++;
71    count_mutex.unlock();
72
73    while (fileIdx < inputFiles.size()) {
74        size_t grepResult = grepEngine->doGrep(inputFiles[fileIdx], fileIdx);
75       
76        count_mutex.lock();
77        if (grepResult > 0) grepMatchFound = true;
78        fileIdx = fileCount;
79        fileCount++;
80        count_mutex.unlock();
81        if (QuietMode && grepMatchFound) pthread_exit(nullptr);
82    }
83
84    pthread_exit(nullptr);
85}
86
87
88
89void GrepEngine::doGrep(const std::string & fileName) const{
90#ifdef CUDA_ENABLED
91    const bool CountOnly = true;
92    boost::filesystem::path file(fileName);
93    if (exists(file)) {
94        if (is_directory(file)) {
95            return;
96        }
97    } else {
98        if (!NoMessagesFlag) {
99            std::cerr << "Error: cannot open " << fileName << " for processing. Skipped.\n";
100            return;
101        }
102    }
103
104    const auto fileSize = file_size(file);
105   
106    if (fileSize > 0) {
107        try {
108            boost::iostreams::mapped_file_source source(fileName, fileSize, 0);
109            char * fileBuffer = const_cast<char *>(source.data());
110           
111            codegen::BlockSize = 128;
112            std::vector<size_t> LFPositions = preprocess(fileBuffer, fileSize);
113           
114            const unsigned numOfGroups = codegen::GroupNum;
115            if (posix_memalign((void**)&startPoints, 8, (numOfGroups+1)*sizeof(size_t)) ||
116                posix_memalign((void**)&accumBytes, 8, (numOfGroups+1)*sizeof(size_t))) {
117                std::cerr << "Cannot allocate memory for startPoints or accumBytes.\n";
118                exit(-1);
119            }
120            const auto PTXFilename = mGrepDriver->getBuilder()->getModule()->getModuleIdentifier() + ".ptx";
121            RunPTX(PTXFilename, fileBuffer, fileSize, CountOnly, LFPositions, startPoints, accumBytes);
122            source.close();
123        } catch (std::exception & e) {
124            if (!NoMessagesFlag) {
125                std::cerr << "Boost mmap error: " + fileName + ": " + e.what() + " Skipped.\n";
126                return;
127            }
128        }
129    } else {
130        std::cout << 0 << std::endl;
131    }
132#endif
133}
134
135uint64_t GrepEngine::doGrep(const std::string & fileName, const uint32_t fileIdx) const {
136    struct stat sb;
137    const int32_t fd = open(fileName.c_str(), O_RDONLY);
138    if (LLVM_UNLIKELY(fd == -1)) {
139        if (!NoMessagesFlag  && !(Mode == QuietMode)) {
140            if (errno == EACCES) {
141                resultStrs[fileIdx] << "icgrep: " << fileName << ": Permission denied.\n";
142            }
143            else if (errno == ENOENT) {
144                resultStrs[fileIdx] << "icgrep: " << fileName << ": No such file.\n";
145            }
146            else {
147                resultStrs[fileIdx] << "icgrep: " << fileName << ": Failed.\n";
148            }
149        }
150        return 0;
151    }
152    if (stat(fileName.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) {
153        if (!NoMessagesFlag  && !(Mode == QuietMode)) {
154            resultStrs[fileIdx] << "icgrep: " << fileName << ": Is a directory.\n";
155        }
156        close(fd);
157        return 0;
158    }
159    const auto result = doGrep(fd, fileIdx);
160    close(fd);
161    return result;
162}
163
164uint64_t GrepEngine::doGrep(const int32_t fileDescriptor, const uint32_t fileIdx) const {
165    assert (mGrepDriver);
166    typedef uint64_t (*GrepFunctionType)(int32_t fileDescriptor, const uint32_t fileIdx);
167    auto f = reinterpret_cast<GrepFunctionType>(mGrepDriver->getMain());
168   
169    uint64_t grepResult = f(fileDescriptor, fileIdx);
170    if (grepResult > 0) grepMatchFound = true;
171    else if ((Mode == NormalMode) && !resultStrs[fileIdx].str().empty()) grepMatchFound = true;
172   
173    if (Mode == CountOnly) {
174        resultStrs[fileIdx] << linePrefix[fileIdx] << grepResult << "\n";
175    }
176    else if (Mode == FilesWithMatch || Mode == FilesWithoutMatch ) {
177        size_t requiredCount = Mode == FilesWithMatch ? 1 : 0;
178        if (grepResult == requiredCount) {
179            resultStrs[fileIdx] << linePrefix[fileIdx];
180        }
181    }
182    else if (Mode == QuietMode) {
183        if (grepMatchFound) exit(MatchFoundExitCode);
184    }
185    return grepResult;
186}
187
188void initFileResult(std::vector<std::string> filenames){
189    grepMatchFound = false;
190    const int n = filenames.size();
191    linePrefix.resize(n);
192    if ((n > 1) && !NoFilenameFlag) {
193        WithFilenameFlag = true;
194    }
195    std::string fileSuffix = "";
196    bool setLinePrefix = WithFilenameFlag || (Mode == FilesWithMatch) || (Mode == FilesWithoutMatch);
197    if (setLinePrefix) {
198        if (NullFlag) {
199            fileSuffix = std::string("\0", 1);
200        }
201        else if ((Mode == NormalMode) && InitialTabFlag && !(LineNumberFlag || ByteOffsetFlag)) {
202            fileSuffix = "\t:";
203        }
204        else if ((Mode == NormalMode) || (Mode == CountOnly)) {
205            fileSuffix = ":";
206        }
207        else if ((Mode == FilesWithMatch) || (Mode == FilesWithoutMatch)) {
208            fileSuffix = "\n";
209        }
210    }
211    inputFiles = filenames;
212    resultStrs = new std::stringstream[n];
213    for (unsigned i = 0; i < inputFiles.size(); ++i) {
214        if (setLinePrefix) {
215            if (inputFiles[i] == "-") {
216                linePrefix[i] = LabelFlag + fileSuffix;
217            }
218            else {
219                linePrefix[i] = inputFiles[i] + fileSuffix;
220            }
221        }
222    }
223}
224
225template<typename CodeUnit>
226void wrapped_report_match(const size_t lineNum, size_t line_start, size_t line_end, const CodeUnit * const buffer, const size_t filesize, const size_t fileIdx) {
227
228//    errs().write_hex((size_t)buffer) << " : " << lineNum << " (" << line_start << ", " << line_end << ", " << filesize << ")\n";
229
230    assert (buffer);
231    assert (line_start <= line_end);
232    assert (line_end <= filesize);
233
234    if (WithFilenameFlag) {
235        resultStrs[fileIdx] << linePrefix[fileIdx];
236    }
237    if (LineNumberFlag) {
238        // Internally line numbers are counted from 0.  For display, adjust
239        // the line number so that lines are numbered from 1.
240        if (InitialTabFlag) {
241            resultStrs[fileIdx] << lineNum+1 << "\t:";
242        }
243        else {
244            resultStrs[fileIdx] << lineNum+1 << ":";
245        }
246    }
247
248    // If the line "starts" on the LF of a CRLF, it is actually the end of the last line.
249    if ((buffer[line_start] == 0xA) && (line_start != line_end)) {
250        ++line_start;
251    }
252
253    if (LLVM_UNLIKELY(line_end == filesize)) {
254        // The match position is at end-of-file.   We have a final unterminated line.
255        resultStrs[fileIdx].write((char *)&buffer[line_start], (line_end - line_start) * sizeof(CodeUnit));
256        if (NormalizeLineBreaksFlag) {
257            resultStrs[fileIdx] << '\n';  // terminate it
258        }
259    } else {
260        const auto end_byte = buffer[line_end];
261        if (grep::NormalizeLineBreaksFlag) {
262            if (LLVM_UNLIKELY(end_byte == 0x85)) {
263                // Line terminated with NEL, on the second byte.  Back up 1.
264                line_end -= 1;
265            } else if (LLVM_UNLIKELY(end_byte > 0xD)) {
266                // Line terminated with PS or LS, on the third byte.  Back up 2.
267                line_end -= 2;
268            }
269            resultStrs[fileIdx].write((char *)&buffer[line_start], (line_end - line_start) * sizeof(CodeUnit));
270            resultStrs[fileIdx] << '\n';
271        } else {
272            if (end_byte == 0x0D) {
273                // Check for line_end on first byte of CRLF; we don't want to access past the end of buffer.
274                if ((line_end + 1) < filesize) {
275                    if (buffer[line_end + 1] == 0x0A) {
276                        // Found CRLF; preserve both bytes.
277                        ++line_end;
278                    }
279                }
280            }
281            resultStrs[fileIdx].write((char *)&buffer[line_start], (line_end - line_start + 1) * sizeof(CodeUnit));
282        }
283    }
284}
285
286void PrintResults(){
287   
288    for (unsigned i = 0; i < inputFiles.size(); ++i){
289        std::cout << resultStrs[i].str();
290    }
291    exit(grepMatchFound ? MatchFoundExitCode : MatchNotFoundExitCode);
292}
293
294void GrepEngine::grepCodeGen_nvptx(std::vector<re::RE *> REs, const GrepModeType grepMode, const bool UTF_16) {
295
296    assert (mGrepDriver == nullptr);
297
298    mGrepDriver = new NVPTXDriver("engine");
299    auto & idb = mGrepDriver->getBuilder();
300    Module * M = idb->getModule();
301
302    const unsigned segmentSize = codegen::SegmentSize;
303    const unsigned bufferSegments = codegen::BufferSegments * codegen::ThreadNum;
304    const unsigned encodingBits = UTF_16 ? 16 : 8;
305
306    Type * const int64Ty = idb->getInt64Ty();
307    Type * const int32Ty = idb->getInt32Ty();
308    Type * const size_ty = idb->getSizeTy();
309    Type * const sizeTyPtr = PointerType::get(size_ty, 1);
310    Type * const int64tyPtr = PointerType::get(int64Ty, 1);
311    Type * const voidTy = idb->getVoidTy();
312
313    Function * mainFunc = cast<Function>(M->getOrInsertFunction("Main", voidTy, int64tyPtr, sizeTyPtr, sizeTyPtr, int64tyPtr, nullptr));
314    mainFunc->setCallingConv(CallingConv::C);
315    idb->SetInsertPoint(BasicBlock::Create(M->getContext(), "entry", mainFunc, 0));
316    auto args = mainFunc->arg_begin();
317
318    Value * const inputPtr = &*(args++);
319    inputPtr->setName("inputPtr");
320    Value * const startPointsPtr = &*(args++);
321    startPointsPtr->setName("startPointsPtr");
322    Value * const bufferSizesPtr = &*(args++);
323    bufferSizesPtr->setName("bufferSizesPtr");
324    Value * const outputPtr = &*(args++);
325    outputPtr->setName("outputPtr");
326
327    Function * tidFunc = M->getFunction("llvm.nvvm.read.ptx.sreg.tid.x");
328    Value * tid = idb->CreateCall(tidFunc);
329    Function * bidFunc = cast<Function>(M->getOrInsertFunction("llvm.nvvm.read.ptx.sreg.ctaid.x", int32Ty, nullptr));
330    Value * bid = idb->CreateCall(bidFunc);
331
332    Value * startPoint = idb->CreateLoad(idb->CreateGEP(startPointsPtr, bid));
333    Value * startBlock = idb->CreateUDiv(startPoint, ConstantInt::get(int64Ty, idb->getBitBlockWidth()));
334    Type * const inputStreamType = PointerType::get(ArrayType::get(ArrayType::get(idb->getBitBlockType(), 8), 1), 1);   
335    Value * inputStreamPtr = idb->CreateGEP(idb->CreateBitCast(inputPtr, inputStreamType), startBlock);
336    Value * inputStream = idb->CreateGEP(inputStreamPtr, tid);
337    Value * bufferSize = idb->CreateLoad(idb->CreateGEP(bufferSizesPtr, bid));
338
339    StreamSetBuffer * ByteStream = mGrepDriver->addBuffer(make_unique<SourceBuffer>(idb, idb->getStreamSetTy(1, 8), 1));
340    kernel::Kernel * sourceK = mGrepDriver->addKernelInstance(make_unique<kernel::MemorySourceKernel>(idb, inputStreamType, segmentSize));
341    sourceK->setInitialArguments({inputStream, bufferSize});
342    mGrepDriver->makeKernelCall(sourceK, {}, {ByteStream});
343
344    StreamSetBuffer * BasisBits = mGrepDriver->addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(8, 1), segmentSize * bufferSegments));
345    kernel::Kernel * s2pk = mGrepDriver->addKernelInstance(make_unique<kernel::S2PKernel>(idb));
346    mGrepDriver->makeKernelCall(s2pk, {ByteStream}, {BasisBits});
347 
348    StreamSetBuffer * LineBreakStream = mGrepDriver->addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(1, 1), segmentSize * bufferSegments));
349    kernel::Kernel * linebreakK = mGrepDriver->addKernelInstance(make_unique<kernel::LineBreakKernelBuilder>(idb, encodingBits));
350    mGrepDriver->makeKernelCall(linebreakK, {BasisBits}, {LineBreakStream});
351   
352    const auto n = REs.size();
353
354    std::vector<StreamSetBuffer *> MatchResultsBufs(n);
355
356    for(unsigned i = 0; i < n; ++i){
357        StreamSetBuffer * MatchResults = mGrepDriver->addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(1, 1), segmentSize * bufferSegments));
358        kernel::Kernel * icgrepK = mGrepDriver->addKernelInstance(make_unique<kernel::ICGrepKernel>(idb, REs[i]));
359        mGrepDriver->makeKernelCall(icgrepK, {BasisBits, LineBreakStream}, {MatchResults});
360        MatchResultsBufs[i] = MatchResults;
361    }
362    StreamSetBuffer * MergedResults = MatchResultsBufs[0];
363    if (REs.size() > 1) {
364        MergedResults = mGrepDriver->addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(1, 1), segmentSize * bufferSegments));
365        kernel::Kernel * streamsMergeK = mGrepDriver->addKernelInstance(make_unique<kernel::StreamsMerge>(idb, 1, REs.size()));
366        mGrepDriver->makeKernelCall(streamsMergeK, MatchResultsBufs, {MergedResults});
367    }
368
369    kernel::MatchCount matchCountK(idb);
370    mGrepDriver->addKernelCall(matchCountK, {MergedResults}, {});
371    mGrepDriver->generatePipelineIR();
372
373    idb->setKernel(&matchCountK);
374    Value * matchedLineCount = idb->getScalarField("matchedLineCount");
375    matchedLineCount = idb->CreateZExt(matchedLineCount, int64Ty);
376   
377    Value * strideBlocks = ConstantInt::get(int32Ty, idb->getStride() / idb->getBitBlockWidth());
378    Value * outputThreadPtr = idb->CreateGEP(outputPtr, idb->CreateAdd(idb->CreateMul(bid, strideBlocks), tid));
379    idb->CreateStore(matchedLineCount, outputThreadPtr);
380    idb->CreateRetVoid();
381
382    mGrepDriver->finalizeObject();
383}
384
385void GrepEngine::grepCodeGen(std::vector<re::RE *> REs, const GrepModeType grepMode, const bool UTF_16, GrepSource grepSource) {
386
387    assert (mGrepDriver == nullptr);
388    mGrepDriver = new ParabixDriver("engine");
389    auto & idb = mGrepDriver->getBuilder();
390    Module * M = idb->getModule();
391
392    const unsigned segmentSize = codegen::SegmentSize;
393    const unsigned bufferSegments = codegen::BufferSegments * codegen::ThreadNum;
394    const unsigned encodingBits = UTF_16 ? 16 : 8;
395
396    Type * const int64Ty = idb->getInt64Ty();
397    Type * const int32Ty = idb->getInt32Ty();
398
399    kernel::Kernel * sourceK = nullptr;
400   
401    size_t MatchLimit = ((grepMode == QuietMode) | (grepMode == FilesWithMatch) | (grepMode == FilesWithoutMatch)) ? 1 : MaxCountFlag;
402
403    Function * mainFunc = cast<Function>(M->getOrInsertFunction("Main", int64Ty, idb->getInt32Ty(), int32Ty, nullptr));
404    mainFunc->setCallingConv(CallingConv::C);
405    idb->SetInsertPoint(BasicBlock::Create(M->getContext(), "entry", mainFunc, 0));
406    auto args = mainFunc->arg_begin();
407
408    Value * const fileDescriptor = &*(args++);
409    fileDescriptor->setName("fileDescriptor");
410    Value * fileIdx = &*(args++);
411    fileIdx->setName("fileIdx");
412
413    StreamSetBuffer * ByteStream = mGrepDriver->addBuffer(make_unique<SourceBuffer>(idb, idb->getStreamSetTy(1, 8)));
414
415    if (grepSource == GrepSource::File) {
416        sourceK = mGrepDriver->addKernelInstance(make_unique<kernel::MMapSourceKernel>(idb, segmentSize));
417    } else {
418        sourceK = mGrepDriver->addKernelInstance(make_unique<kernel::ReadSourceKernel>(idb, segmentSize));
419    }
420    sourceK->setInitialArguments({fileDescriptor});
421
422    mGrepDriver->makeKernelCall(sourceK, {}, {ByteStream});
423    StreamSetBuffer * BasisBits = mGrepDriver->addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(8, 1), segmentSize * bufferSegments));
424   
425    kernel::Kernel * s2pk = mGrepDriver->addKernelInstance(make_unique<kernel::S2PKernel>(idb));
426    mGrepDriver->makeKernelCall(s2pk, {ByteStream}, {BasisBits});
427   
428    kernel::Kernel * linebreakK = mGrepDriver->addKernelInstance(make_unique<kernel::LineBreakKernelBuilder>(idb, encodingBits));
429    StreamSetBuffer * LineBreakStream = mGrepDriver->addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(1, 1), segmentSize * bufferSegments));
430    mGrepDriver->makeKernelCall(linebreakK, {BasisBits}, {LineBreakStream});
431   
432    const auto n = REs.size();
433
434    std::vector<StreamSetBuffer *> MatchResultsBufs(n);
435
436    for(unsigned i = 0; i < n; ++i){
437        StreamSetBuffer * MatchResults = mGrepDriver->addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(1, 1), segmentSize * bufferSegments));
438        kernel::Kernel * icgrepK = mGrepDriver->addKernelInstance(make_unique<kernel::ICGrepKernel>(idb, REs[i]));
439        mGrepDriver->makeKernelCall(icgrepK, {BasisBits, LineBreakStream}, {MatchResults});
440        MatchResultsBufs[i] = MatchResults;
441    }
442    StreamSetBuffer * MergedResults = MatchResultsBufs[0];
443    if (REs.size() > 1) {
444        MergedResults = mGrepDriver->addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(1, 1), segmentSize * bufferSegments));
445        kernel::Kernel * streamsMergeK = mGrepDriver->addKernelInstance(make_unique<kernel::StreamsMerge>(idb, 1, REs.size()));
446        mGrepDriver->makeKernelCall(streamsMergeK, MatchResultsBufs, {MergedResults});
447    }
448   
449    if (InvertMatchFlag) {
450        kernel::Kernel * invertK = mGrepDriver->addKernelInstance(make_unique<kernel::InvertMatchesKernel>(idb));
451        StreamSetBuffer * OriginalMatches = MergedResults;
452        MergedResults = mGrepDriver->addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(1, 1), segmentSize * bufferSegments));
453        mGrepDriver->makeKernelCall(invertK, {OriginalMatches, LineBreakStream}, {MergedResults});
454    }
455    if (MatchLimit > 0) {
456        kernel::Kernel * untilK = mGrepDriver->addKernelInstance(make_unique<kernel::UntilNkernel>(idb));
457        untilK->setInitialArguments({idb->getSize(MatchLimit)});
458        StreamSetBuffer * AllMatches = MergedResults;
459        MergedResults = mGrepDriver->addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(1, 1), segmentSize * bufferSegments));
460        mGrepDriver->makeKernelCall(untilK, {AllMatches}, {MergedResults});
461    }
462    if (grepMode == NormalMode) {
463        kernel::Kernel * scanMatchK = mGrepDriver->addKernelInstance(make_unique<kernel::ScanMatchKernel>(idb, GrepType::Normal, encodingBits));
464        scanMatchK->setInitialArguments({fileIdx});
465        mGrepDriver->makeKernelCall(scanMatchK, {MergedResults, LineBreakStream, ByteStream}, {});
466        if (UTF_16) {
467            mGrepDriver->LinkFunction(*scanMatchK, "matcher", &wrapped_report_match<uint16_t>);
468        } else {
469            mGrepDriver->LinkFunction(*scanMatchK, "matcher", &wrapped_report_match<uint8_t>);
470        }
471        mGrepDriver->generatePipelineIR();
472        idb->CreateRet(idb->getInt64(0));
473    } else {
474        kernel::Kernel * matchCountK = mGrepDriver->addKernelInstance(make_unique<kernel::MatchCount>(idb));
475        mGrepDriver->makeKernelCall(matchCountK, {MergedResults}, {});
476        mGrepDriver->generatePipelineIR();
477        idb->setKernel(matchCountK);
478        Value * matchedLineCount = idb->getScalarField("matchedLineCount");
479        matchedLineCount = idb->CreateZExt(matchedLineCount, int64Ty);
480        idb->CreateRet(matchedLineCount);
481    }
482    mGrepDriver->finalizeObject();
483}
484
485GrepEngine::GrepEngine()
486: mGrepDriver(nullptr) {
487
488}
489
490GrepEngine::~GrepEngine() {
491    delete mGrepDriver;
492}
493
494
495   
496static re::CC * parsedCodePointSet = nullptr;
497
498void insert_codepoints(const size_t lineNum, const size_t line_start, const size_t line_end, const char * const buffer) {
499    assert (buffer);
500    assert (line_start <= line_end);
501    re::codepoint_t c = 0;
502    size_t line_pos = line_start;
503    while (isxdigit(buffer[line_pos])) {
504        assert (line_pos < line_end);
505        if (isdigit(buffer[line_pos])) {
506            c = (c << 4) | (buffer[line_pos] - '0');
507        }
508        else {
509            c = (c << 4) | (tolower(buffer[line_pos]) - 'a' + 10);
510        }
511        line_pos++;
512    }
513    assert(((line_pos - line_start) >= 4) && ((line_pos - line_start) <= 6)); // UCD format 4 to 6 hex digits.
514    parsedCodePointSet->insert(c);
515}
516
517re::CC * grepCodepoints(re::RE * pattern, char * UnicodeDataBuffer, size_t bufferLength) {
518    parsedCodePointSet = re::makeCC();       
519    const unsigned segmentSize = 8;
520
521    ParabixDriver pxDriver("codepointEngine");
522    auto & idb = pxDriver.getBuilder();
523    Module * M = idb->getModule();
524   
525    Function * mainFunc = cast<Function>(M->getOrInsertFunction("Main", idb->getVoidTy(), idb->getInt8PtrTy(), idb->getSizeTy(), nullptr));
526    mainFunc->setCallingConv(CallingConv::C);
527    auto args = mainFunc->arg_begin();
528    Value * const buffer = &*(args++);
529    buffer->setName("buffer");
530    Value * length = &*(args++);
531    length->setName("length");
532   
533    idb->SetInsertPoint(BasicBlock::Create(M->getContext(), "entry", mainFunc, 0));
534   
535    StreamSetBuffer * ByteStream = pxDriver.addBuffer(make_unique<SourceBuffer>(idb, idb->getStreamSetTy(1, 8)));
536    kernel::Kernel * sourceK = pxDriver.addKernelInstance(make_unique<kernel::MemorySourceKernel>(idb, idb->getInt8PtrTy(), segmentSize));
537    sourceK->setInitialArguments({buffer, length});
538    pxDriver.makeKernelCall(sourceK, {}, {ByteStream});
539   
540    StreamSetBuffer * BasisBits = pxDriver.addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(8, 1), segmentSize));
541   
542    kernel::Kernel * s2pk = pxDriver.addKernelInstance(make_unique<kernel::S2PKernel>(idb));
543    pxDriver.makeKernelCall(s2pk, {ByteStream}, {BasisBits});
544   
545    kernel::Kernel * linebreakK = pxDriver.addKernelInstance(make_unique<kernel::LineBreakKernelBuilder>(idb, 8));
546    StreamSetBuffer * LineBreakStream = pxDriver.addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(1, 1), segmentSize));
547    pxDriver.makeKernelCall(linebreakK, {BasisBits}, {LineBreakStream});
548   
549    StreamSetBuffer * MatchResults = pxDriver.addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(1, 1), segmentSize));
550    kernel::Kernel * icgrepK = pxDriver.addKernelInstance(make_unique<kernel::ICGrepKernel>(idb, pattern));
551    pxDriver.makeKernelCall(icgrepK, {BasisBits, LineBreakStream}, {MatchResults});
552   
553    kernel::Kernel * scanMatchK = pxDriver.addKernelInstance(make_unique<kernel::ScanMatchKernel>(idb, GrepType::NameExpression, 8));
554    scanMatchK->setInitialArguments({idb->getInt32(0)});
555    pxDriver.makeKernelCall(scanMatchK, {MatchResults, LineBreakStream, ByteStream}, {});
556    pxDriver.LinkFunction(*scanMatchK, "matcher", &insert_codepoints);
557    pxDriver.generatePipelineIR();
558    idb->CreateRetVoid();
559    pxDriver.finalizeObject();
560   
561    typedef void (*GrepFunctionType)(const char * buffer, const size_t length);
562    auto f = reinterpret_cast<GrepFunctionType>(pxDriver.getMain());
563    f(UnicodeDataBuffer, bufferLength);
564   
565    return parsedCodePointSet;   
566}
567
568   
569static std::vector<std::string> parsedPropertyValues;
570
571void insert_property_values(size_t lineNum, size_t line_start, size_t line_end, const char * buffer) {
572    assert (line_start <= line_end);
573    parsedPropertyValues.emplace_back(buffer + line_start, buffer + line_end);
574}
575
576
577const std::vector<std::string> & grepPropertyValues(const std::string& propertyName, re::RE * propertyValuePattern) {
578    ParabixDriver pxDriver("propertyValueEngine");
579    AlignedAllocator<char, 32> alloc;
580
581    parsedPropertyValues.clear();
582
583    const std::string & str = UCD::getPropertyValueGrepString(propertyName);
584
585    auto & idb = pxDriver.getBuilder();
586
587    const unsigned segmentSize = 8;
588    const auto n = str.length();
589    const auto w = idb->getBitBlockWidth() * segmentSize;
590    const auto m = w - (n % w);
591
592    char * aligned = alloc.allocate(n + m, 0);
593    std::memcpy(aligned, str.data(), n);
594    std::memset(aligned + n, 0, m);
595
596    Module * M = idb->getModule();
597   
598    Function * mainFunc = cast<Function>(M->getOrInsertFunction("Main", idb->getVoidTy(), idb->getInt8PtrTy(), idb->getSizeTy(), nullptr));
599    mainFunc->setCallingConv(CallingConv::C);
600    auto args = mainFunc->arg_begin();
601    Value * const buffer = &*(args++);
602    buffer->setName("buffer");
603    Value * length = &*(args++);
604    length->setName("length");
605   
606    idb->SetInsertPoint(BasicBlock::Create(M->getContext(), "entry", mainFunc, 0));
607   
608    StreamSetBuffer * ByteStream = pxDriver.addBuffer(make_unique<SourceBuffer>(idb, idb->getStreamSetTy(1, 8)));
609    kernel::Kernel * sourceK = pxDriver.addKernelInstance(make_unique<kernel::MemorySourceKernel>(idb, idb->getInt8PtrTy(), segmentSize));
610    sourceK->setInitialArguments({buffer, length});
611    pxDriver.makeKernelCall(sourceK, {}, {ByteStream});
612   
613    StreamSetBuffer * BasisBits = pxDriver.addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(8, 1), segmentSize));
614   
615    kernel::Kernel * s2pk = pxDriver.addKernelInstance(make_unique<kernel::S2PKernel>(idb));
616    pxDriver.makeKernelCall(s2pk, {ByteStream}, {BasisBits});
617   
618    kernel::Kernel * linebreakK = pxDriver.addKernelInstance(make_unique<kernel::LineBreakKernelBuilder>(idb, 8));
619    StreamSetBuffer * LineBreakStream = pxDriver.addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(1, 1), segmentSize));
620    pxDriver.makeKernelCall(linebreakK, {BasisBits}, {LineBreakStream});
621   
622    StreamSetBuffer * MatchResults = pxDriver.addBuffer(make_unique<CircularBuffer>(idb, idb->getStreamSetTy(1, 1), segmentSize));
623    kernel::Kernel * icgrepK = pxDriver.addKernelInstance(make_unique<kernel::ICGrepKernel>(idb, propertyValuePattern));
624    pxDriver.makeKernelCall(icgrepK, {BasisBits, LineBreakStream}, {MatchResults});
625   
626    kernel::Kernel * scanMatchK = pxDriver.addKernelInstance(make_unique<kernel::ScanMatchKernel>(idb, GrepType::PropertyValue, 8));
627    scanMatchK->setInitialArguments({idb->getInt32(0)});
628    pxDriver.makeKernelCall(scanMatchK, {MatchResults, LineBreakStream, ByteStream}, {});
629    pxDriver.LinkFunction(*scanMatchK, "matcher", &insert_property_values);
630    pxDriver.generatePipelineIR();
631    idb->CreateRetVoid();
632    pxDriver.finalizeObject();
633
634    typedef void (*GrepFunctionType)(const char * buffer, const size_t length);
635    auto f = reinterpret_cast<GrepFunctionType>(pxDriver.getMain());
636    f(aligned, n);
637   
638    alloc.deallocate(aligned, 0);
639    return parsedPropertyValues;
640}
641
642   
643}
Note: See TracBrowser for help on using the repository browser.