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

Last change on this file since 5550 was 5550, checked in by lindanl, 23 months ago

Use exsiting PTX file.

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