source: icGREP/icgrep-devel/icgrep/icgrep.cpp @ 5682

Last change on this file since 5682 was 5620, checked in by nmedfort, 23 months ago

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

File size: 7.7 KB
Line 
1/*
2 *  Copyright (c) 2016 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 <cstdio>
8#include <vector>
9#include <llvm/Support/CommandLine.h>
10#include <llvm/Support/ErrorHandling.h>
11#include <llvm/Support/Signals.h>
12#include <llvm/Support/raw_ostream.h>
13#include <re/re_alt.h>
14#include <re/re_seq.h>
15#include <re/re_start.h>
16#include <re/re_end.h>
17#include <re/re_parser.h>
18#include <re/re_utility.h>
19#include <grep_engine.h>
20#include <grep_interface.h>
21#include <fstream>
22#include <string>
23#include <toolchain/toolchain.h>
24#include <re/re_toolchain.h>
25#include <pablo/pablo_toolchain.h>
26#include <boost/filesystem.hpp>
27#include <iostream> // MEEE
28#ifdef PRINT_TIMING_INFORMATION
29#include <hrtime.h>
30#include <util/papi_helper.hpp>
31#endif
32#include <sys/stat.h>
33#include <fcntl.h>
34
35using namespace llvm;
36
37static cl::opt<bool> UTF_16("UTF-16", cl::desc("Regular expressions over the UTF-16 representation of Unicode."));
38
39static cl::list<std::string> inputFiles(cl::Positional, cl::desc("<regex> <input file ...>"), cl::OneOrMore);
40
41static cl::opt<int> Threads("t", cl::desc("Total number of threads."), cl::init(1));
42
43static cl::opt<bool> ByteMode("enable-byte-mode", cl::desc("Process regular expressions in byte mode"));
44
45static cl::opt<bool> MultiGrepKernels("enable-multigrep-kernels", cl::desc("Construct separated kernels for each regular expression"));
46static cl::opt<int> REsPerGroup("re-num", cl::desc("Number of regular expressions processed by each kernel."), cl::init(1));
47
48static cl::opt<std::string> PTXFile("ptx", cl::desc("compiled PTX file."), cl::init(""));
49
50static std::vector<std::string> allFiles;
51static re::ModeFlagSet globalFlags = 0;
52
53std::vector<re::RE *> readExpressions() {
54 
55    if (grep::FileFlag != "") {
56        std::ifstream regexFile(grep::FileFlag.c_str());
57        std::string r;
58        if (regexFile.is_open()) {
59            while (std::getline(regexFile, r)) {
60                grep::RegexpVector.push_back(r);
61            }
62            regexFile.close();
63        }
64    }
65   
66    // if there are no regexes specified through -e or -f, the first positional argument
67    // must be a regex, not an input file.
68   
69    if (grep::RegexpVector.size() == 0) {
70        grep::RegexpVector.push_back(inputFiles[0]);
71        inputFiles.erase(inputFiles.begin());
72    }
73    if (grep::IgnoreCaseFlag) {
74        globalFlags |= re::CASE_INSENSITIVE_MODE_FLAG;
75    }
76
77    std::vector<re::RE *> REs;
78    for (unsigned i = 0; i < grep::RegexpVector.size(); i++) {
79        re::RE * re_ast = re::RE_Parser::parse(grep::RegexpVector[i], globalFlags, grep::RegexpSyntax, ByteMode);
80        REs.push_back(re_ast);
81    }
82
83    if (MultiGrepKernels) {
84        std::vector<re::RE *> groups;
85        auto start = REs.begin();
86        auto end = start + REsPerGroup;
87        while (end < REs.end()) {
88            groups.push_back(re::makeAlt(start, end));
89            start = end;
90            end += REsPerGroup;
91        }
92        if ((REs.end() - start) > 1) {
93            groups.push_back(re::makeAlt(start, REs.end()));
94        } else {
95            groups.push_back(*start);
96        }
97        REs.swap(groups);
98    } else if (REs.size() > 1) {
99        REs.assign({re::makeAlt(REs.begin(), REs.end())});
100    }
101
102    for (re::RE *& re_ast : REs) {
103        assert (re_ast);
104        if (grep::WordRegexpFlag) {
105            re_ast = re::makeSeq({re::makeWordBoundary(), re_ast, re::makeWordBoundary()});
106        }
107        if (grep::LineRegexpFlag) {
108            re_ast = re::makeSeq({re::makeStart(), re_ast, re::makeEnd()});
109        }
110    }
111
112    return REs;
113}
114
115
116// This is a stub, to be expanded later.
117bool excludeDirectory(boost::filesystem::path dirpath) { return dirpath.filename() == ".svn";}
118
119// Determine whether to skip a path based on -D skip or -d skip settings.
120bool skip_path(boost::filesystem::path p) {
121    using namespace boost::filesystem;
122    switch (status(p).type()) {
123        case directory_file: return grep::DirectoriesFlag == grep::Skip;
124        case block_file:
125        case character_file:
126        case fifo_file:
127        case socket_file:
128            return grep::DevicesFlag == grep::Skip;
129        default:
130            return false;
131    }
132}
133
134std::vector<std::string> getFullFileList(cl::list<std::string> & inputFiles) {
135    using namespace boost::filesystem;
136    symlink_option follow_symlink = grep::DereferenceRecursiveFlag ? symlink_option::recurse : symlink_option::none;
137    std::vector<std::string> expanded_paths;
138    boost::system::error_code errc;
139    for (const std::string & f : inputFiles) {
140        //        if (f == "-") {
141        //            continue;
142        //        }
143        path p(f);
144        if (skip_path(p)) {
145            continue;
146        }
147        if (LLVM_UNLIKELY((grep::DirectoriesFlag == grep::Recurse) && is_directory(p))) {
148            if (!excludeDirectory(p)) {
149                recursive_directory_iterator di(p, follow_symlink, errc), end;
150                if (errc) {
151                    // If we cannot enter the directory, keep it in the list of files.
152                    expanded_paths.push_back(f);
153                    continue;
154                }
155                while (di != end) {
156                    auto & e = di->path();
157                    if (is_directory(e)) {
158                        if (LLVM_UNLIKELY(excludeDirectory(e))) {
159                            di.no_push();
160                        }
161                    } else {
162                        if (!skip_path(e)) expanded_paths.push_back(e.string());
163                    }
164                    di.increment(errc);
165                    if (errc) {
166                        expanded_paths.push_back(e.string());
167                    }
168                }
169            }
170        } else {
171            expanded_paths.push_back(p.string());
172        }
173    }
174    return expanded_paths;
175}
176
177int main(int argc, char *argv[]) {
178
179    grep::InitializeCommandLineInterface(argc, argv);
180   
181    const auto REs = readExpressions();
182
183    allFiles = getFullFileList(inputFiles);
184
185    grep::GrepEngine grepEngine;
186
187    if (allFiles.empty()) {
188
189        grepEngine.grepCodeGen(REs, grep::Mode, UTF_16, GrepSource::StdIn);
190        allFiles = { "-" };
191        grep::initFileResult(allFiles);
192        grepEngine.doGrep(STDIN_FILENO, 0);
193
194    } else {
195               
196        if (codegen::NVPTX) {
197            if(PTXFile=="")
198                grepEngine.grepCodeGen_nvptx(REs, grep::Mode, UTF_16);
199            for (unsigned i = 0; i != allFiles.size(); ++i) {
200                grepEngine.doGrep(allFiles[i], PTXFile);
201            }
202            return 0;
203        } else {
204            grepEngine.grepCodeGen(REs, grep::Mode, UTF_16, GrepSource::File);
205        }
206
207        grep::initFileResult(allFiles);
208
209        if (Threads <= 1) {
210            for (unsigned i = 0; i != allFiles.size(); ++i) {
211                grepEngine.doGrep(allFiles[i], i);
212            }
213        } else if (Threads > 1) {
214            const unsigned numOfThreads = Threads; // <- convert the command line value into an integer to allow stack allocation
215            pthread_t threads[numOfThreads];
216
217            for(unsigned long i = 0; i < numOfThreads; ++i){
218                const int rc = pthread_create(&threads[i], nullptr, grep::DoGrepThreadFunction, (void *)&grepEngine);
219                if (rc) {
220                    llvm::report_fatal_error("Failed to create thread: code " + std::to_string(rc));
221                }
222            }
223            for(unsigned i = 0; i < numOfThreads; ++i) {
224                void * status = nullptr;
225                const int rc = pthread_join(threads[i], &status);
226                if (rc) {
227                    llvm::report_fatal_error("Failed to join thread: code " + std::to_string(rc));
228                }
229            }
230        }
231
232    }
233   
234    grep::PrintResults();
235   
236    return 0;
237}
Note: See TracBrowser for help on using the repository browser.