OmniSciDB  d2f719934e
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UdfCompiler.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2021 OmniSci, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "UdfCompiler.h"
18 
19 #include <clang/AST/AST.h>
20 #include <clang/AST/ASTConsumer.h>
21 #include <clang/AST/RecursiveASTVisitor.h>
22 #include <clang/Driver/Compilation.h>
23 #include <clang/Driver/Driver.h>
24 #include <clang/Frontend/CompilerInstance.h>
25 #include <clang/Frontend/FrontendActions.h>
26 #include <clang/Frontend/TextDiagnosticPrinter.h>
27 #include <clang/Parse/ParseAST.h>
28 #include <clang/Tooling/CommonOptionsParser.h>
29 #include <clang/Tooling/Tooling.h>
30 #include <llvm/Support/Program.h>
31 #include <llvm/Support/raw_ostream.h>
32 #include <boost/process/search_path.hpp>
33 #include <iterator>
34 #include <memory>
35 #include "clang/Basic/Version.h"
36 
37 #if LLVM_VERSION_MAJOR >= 11
38 #include <llvm/Support/Host.h>
39 #endif
40 
41 #include "Logger/Logger.h"
42 #include "OSDependent/omnisci_fs.h"
43 
44 using namespace clang;
45 using namespace clang::tooling;
46 
47 static llvm::cl::OptionCategory ToolingSampleCategory("UDF Tooling");
48 
49 namespace {
50 
51 // By implementing RecursiveASTVisitor, we can specify which AST nodes
52 // we're interested in by overriding relevant methods.
53 
54 class FunctionDeclVisitor : public RecursiveASTVisitor<FunctionDeclVisitor> {
55  public:
56  FunctionDeclVisitor(llvm::raw_fd_ostream& ast_file,
57  SourceManager& s_manager,
58  ASTContext& context)
59  : ast_file_(ast_file), source_manager_(s_manager), context_(context) {
60  source_manager_.getDiagnostics().setShowColors(false);
61  }
62 
63  bool VisitFunctionDecl(FunctionDecl* f) {
64  // Only function definitions (with bodies), not declarations.
65  if (f->hasBody()) {
66  if (getMainFileName() == getFuncDeclFileName(f)) {
67  auto printing_policy = context_.getPrintingPolicy();
68  printing_policy.FullyQualifiedName = 1;
69  printing_policy.UseVoidForZeroParams = 1;
70  printing_policy.PolishForDeclaration = 1;
71  printing_policy.TerseOutput = 1;
72  f->print(ast_file_, printing_policy);
73  ast_file_ << "\n";
74  }
75  }
76 
77  return true;
78  }
79 
80  private:
81  std::string getMainFileName() const {
82  auto f_entry = source_manager_.getFileEntryForID(source_manager_.getMainFileID());
83  return f_entry->getName().str();
84  }
85 
86  std::string getFuncDeclFileName(FunctionDecl* f) const {
87  SourceLocation spell_loc = source_manager_.getSpellingLoc(f->getLocation());
88  PresumedLoc p_loc = source_manager_.getPresumedLoc(spell_loc);
89 
90  return std::string(p_loc.getFilename());
91  }
92 
93  private:
94  llvm::raw_fd_ostream& ast_file_;
95  SourceManager& source_manager_;
96  ASTContext& context_;
97 };
98 
99 // Implementation of the ASTConsumer interface for reading an AST produced
100 // by the Clang parser.
101 class DeclASTConsumer : public ASTConsumer {
102  public:
103  DeclASTConsumer(llvm::raw_fd_ostream& ast_file,
104  SourceManager& s_manager,
105  ASTContext& context)
106  : visitor_(ast_file, s_manager, context) {}
107 
108  // Override the method that gets called for each parsed top-level
109  // declaration.
110  bool HandleTopLevelDecl(DeclGroupRef decl_reference) override {
111  for (DeclGroupRef::iterator b = decl_reference.begin(), e = decl_reference.end();
112  b != e;
113  ++b) {
114  // Traverse the declaration using our AST visitor.
115  visitor_.TraverseDecl(*b);
116  }
117  return true;
118  }
119 
120  private:
122 };
123 
124 // For each source file provided to the tool, a new FrontendAction is created.
125 class HandleDeclAction : public ASTFrontendAction {
126  public:
127  HandleDeclAction(llvm::raw_fd_ostream& ast_file) : ast_file_(ast_file) {}
128 
129  ~HandleDeclAction() override {}
130 
131  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance& instance,
132  StringRef file) override {
133  return std::make_unique<DeclASTConsumer>(
134  ast_file_, instance.getSourceManager(), instance.getASTContext());
135  }
136 
137  private:
138  llvm::raw_fd_ostream& ast_file_;
139 };
140 
141 class ToolFactory : public FrontendActionFactory {
142  public:
143 #if LLVM_VERSION_MAJOR >= 10
144  using FrontendActionPtr = std::unique_ptr<clang::FrontendAction>;
145 #define CREATE_FRONTEND_ACTION(ast_file_) std::make_unique<HandleDeclAction>(ast_file_)
146 #else
147  using FrontendActionPtr = clang::FrontendAction*;
148 #define CREATE_FRONTEND_ACTION(ast_file_) new HandleDeclAction(ast_file_)
149 #endif
150 
151  ToolFactory(llvm::raw_fd_ostream& ast_file) : ast_file_(ast_file) {}
152 
153  FrontendActionPtr create() override { return CREATE_FRONTEND_ACTION(ast_file_); }
154 
155  private:
156  llvm::raw_fd_ostream& ast_file_;
157 };
158 
159 const char* convert(const std::string& s) {
160  return s.c_str();
161 }
162 
163 std::string exec_output(std::string cmd) {
164  std::array<char, 128> buffer;
165  std::string result;
166  std::unique_ptr<FILE, decltype(&omnisci::pclose)> pipe(omnisci::popen(cmd.c_str(), "r"),
168  if (!pipe) {
169  throw std::runtime_error("omnisci::popen(\"" + cmd + "\") failed!");
170  }
171  while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
172  result += buffer.data();
173  }
174  return result;
175 }
176 
177 std::tuple<int, int, int> get_clang_version(const std::string& clang_path) {
178  std::string cmd = clang_path + " --version";
179  std::string result = exec_output(cmd);
180  if (result.empty()) {
181  throw std::runtime_error(
182  "Invalid clang binary path detected, cannot find clang binary. Is clang "
183  "installed?");
184  }
185  int major, minor, patchlevel;
186  auto count = sscanf(result.substr(result.find("clang version")).c_str(),
187  "clang version %d.%d.%d",
188  &major,
189  &minor,
190  &patchlevel);
191  if (count != 3) {
192  throw std::runtime_error("Failed to get clang version from output:\n" + result +
193  "\n");
194  }
195  return {major, minor, patchlevel};
196 }
197 
199  public:
200  clang::driver::Driver* getClangDriver() { return &the_driver; }
201  std::tuple<int, int, int> getClangVersion() const { return clang_version; }
202 
203  static UdfClangDriver init(const std::string& clang_path);
204 
205  UdfClangDriver(const UdfClangDriver&) = delete; // no copy
206 
207  protected:
208  UdfClangDriver(const std::string& clang_path,
209  llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diag_options);
210 
211  private:
212  llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diag_options;
213  clang::DiagnosticConsumer* diag_client;
214  llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diag_id;
215  clang::DiagnosticsEngine diags;
216  std::unique_ptr<clang::DiagnosticConsumer> diag_client_owner;
217  clang::driver::Driver the_driver;
218  std::tuple<int, int, int> clang_version;
219 };
220 
221 UdfClangDriver UdfClangDriver::init(const std::string& clang_path) {
222  llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diag_options =
223  new DiagnosticOptions();
224  if (!diag_options) {
225  throw std::runtime_error(
226  "Failed to initialize UDF compiler diagnostic options. Aborting UDF compiler "
227  "initialization. Is clang/clang++ installed?");
228  }
229  return UdfClangDriver(clang_path, diag_options);
230 }
231 
232 UdfClangDriver::UdfClangDriver(
233  const std::string& clang_path,
234  llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diag_options)
235  : diag_options(diag_options)
236  , diag_client(new TextDiagnosticPrinter(llvm::errs(), diag_options.get()))
237  , diag_id(new clang::DiagnosticIDs())
238  , diags(diag_id, diag_options.get(), diag_client)
239  , diag_client_owner(diags.takeClient())
240  , the_driver(clang_path.c_str(), llvm::sys::getDefaultTargetTriple(), diags)
241  , clang_version(get_clang_version(clang_path)) {
242  the_driver.CCPrintOptions = 0;
243 
244  if (!boost::filesystem::exists(the_driver.ResourceDir)) {
245  LOG(WARNING) << "clang driver ResourceDir=" << the_driver.ResourceDir
246  << " does not exist";
247  }
248 
249  // Replace clang driver resource directory with clang compiler
250  // resource directory
251  std::string clang_resource_dir = exec_output(clang_path + " -print-resource-dir");
252 
253  // trim clang_resource_dir string from right
254  clang_resource_dir.erase(
255  std::find_if(clang_resource_dir.rbegin(),
256  clang_resource_dir.rend(),
257  [](unsigned char ch) { return !std::isspace(ch); })
258  .base(),
259  clang_resource_dir.end());
260 
261  if (clang_resource_dir != the_driver.ResourceDir) {
262  LOG(WARNING) << "Resetting clang driver ResourceDir to " << clang_resource_dir
263  << " (was " << the_driver.ResourceDir << ")";
264  the_driver.ResourceDir = clang_resource_dir;
265  }
266 }
267 
268 std::string get_clang_path(const std::string& clang_path_override) {
269  if (clang_path_override.empty()) {
270  const auto clang_path = (llvm::sys::findProgramByName("clang++").get());
271  if (clang_path.empty()) {
272  throw std::runtime_error(
273  "Unable to find clang++ to compile user defined functions");
274  }
275  return clang_path;
276  } else {
277  if (!boost::filesystem::exists(clang_path_override)) {
278  throw std::runtime_error("Path provided for udf compiler " + clang_path_override +
279  " does not exist.");
280  }
281 
282  if (boost::filesystem::is_directory(clang_path_override)) {
283  throw std::runtime_error("Path provided for udf compiler " + clang_path_override +
284  " is not to the clang++ executable.");
285  }
286  }
287  return clang_path_override;
288 }
289 
290 } // namespace
291 
293  const std::string& clang_path_override)
294  : clang_path_(get_clang_path(clang_path_override))
295 #ifdef HAVE_CUDA
296  , target_arch_(target_arch)
297 #endif
298 {
299 }
300 
302  const std::string& clang_path_override,
303  const std::vector<std::string> clang_options)
304  : clang_path_(get_clang_path(clang_path_override))
305  , clang_options_(clang_options)
306 #ifdef HAVE_CUDA
307  , target_arch_(target_arch)
308 #endif
309 {
310 }
311 
312 std::pair<std::string, std::string> UdfCompiler::compileUdf(
313  const std::string& udf_file_name) const {
314  LOG(INFO) << "UDFCompiler filename to compile: " << udf_file_name;
315  if (!boost::filesystem::exists(udf_file_name)) {
316  throw std::runtime_error("User defined function file " + udf_file_name +
317  " does not exist.");
318  }
319 
320  // create the AST file for the input function
321  generateAST(udf_file_name);
322 
323  // Compile udf file to generate cpu and gpu bytecode files
324  std::string cpu_file_name = "";
325  std::string cuda_file_name = "";
326 
327  cpu_file_name = compileToLLVMIR(udf_file_name);
328 
329 #ifdef HAVE_CUDA
330  try {
331  cuda_file_name = compileToNVVMIR(udf_file_name);
332  } catch (const std::exception& e) {
333  LOG(WARNING)
334  << "Failed to generate GPU IR for UDF " + udf_file_name +
335  ", attempting to use CPU compiled IR for GPU.\nUDF Compiler exception: " +
336  e.what();
337  }
338 #endif
339  return std::make_pair(cpu_file_name, cuda_file_name);
340 }
341 
342 namespace {
343 
344 std::string remove_file_extension(const std::string& path) {
345  if (path == "." || path == "..") {
346  return path;
347  }
348 
349  size_t pos = path.find_last_of("\\/.");
350  if (pos != std::string::npos && path[pos] == '.') {
351  return path.substr(0, pos);
352  }
353 
354  return path;
355 }
356 
357 std::string get_file_ext(const std::string& s) {
358  size_t i = s.rfind('.', s.length());
359  if (1 != std::string::npos) {
360  return (s.substr(i + 1, s.length() - i));
361  }
362 }
363 
364 void replace_extension(std::string& s, const std::string& new_ext) {
365  std::string::size_type i = s.rfind('.', s.length());
366 
367  if (i != std::string::npos) {
368  s.replace(i + 1, get_file_ext(s).length(), new_ext);
369  }
370 }
371 
372 } // namespace
373 
374 std::string UdfCompiler::genNVVMIRFilename(const std::string& udf_file_name) {
375  return remove_file_extension(udf_file_name) + "_gpu.bc";
376 }
377 
378 std::string UdfCompiler::genLLVMIRFilename(const std::string& udf_file_name) {
379  return remove_file_extension(udf_file_name) + "_cpu.bc";
380 }
381 
383  const std::vector<std::string>& command_line) const {
384  UdfClangDriver compiler_driver = UdfClangDriver::init(clang_path_);
385  auto the_driver(compiler_driver.getClangDriver());
386 
387  std::vector<const char*> clang_command_opts;
388  clang_command_opts.reserve(command_line.size() + clang_options_.size());
389  // add required options first
390  std::transform(std::begin(command_line),
391  std::end(command_line),
392  std::back_inserter(clang_command_opts),
393  [&](const std::string& str) { return str.c_str(); });
394 
395  // If there were additional clang options passed to the system, append them here
396  if (!clang_options_.empty()) {
397  std::transform(std::begin(clang_options_),
398  std::end(clang_options_),
399  std::back_inserter(clang_command_opts),
400  [&](const std::string& str) { return str.c_str(); });
401  }
402 
403  std::unique_ptr<driver::Compilation> compilation(
404  the_driver->BuildCompilation(clang_command_opts));
405  if (!compilation) {
406  throw std::runtime_error("failed to build compilation object!");
407  }
408  auto [clang_version_major, clang_version_minor, clang_version_patchlevel] =
409  compiler_driver.getClangVersion();
410  if (clang_version_major != CLANG_VERSION_MAJOR
411  // mismatch of clang driver and compulier versions requires
412  // modified workflow that removes incompatible driver flags for
413  // compiler.
414  || CLANG_VERSION_MAJOR == 9
415  // clang driver 9 requires cudatoolkit 8 that we don't support,
416  // hence switching to modified clang compiler 9 workflow that is
417  // able to produce bytecode to GPU when using cudatoolkit 11.
418  ) {
419  /* Fix incompatibilities when driver and clang versions differ.
420  */
421  auto& jobs = compilation->getJobs();
422  CHECK_EQ(jobs.size(), size_t(1));
423  auto& job = *jobs.begin();
424 
425  std::string cmd = job.getExecutable();
426  int skip = 0;
427  std::string last = "";
428 
429  for (auto& arg : job.getArguments()) {
430  const std::string& s = arg;
431  if (skip > 0) {
432  skip--;
433  last = s;
434  continue;
435  }
436 
437  // inclusion of __clang_cuda_runtime_wrapper.h leads to either
438  // clang >9 compilation failure or clang 9 failure for using
439  // cuda >8 (unsupported CUDA version).
440  if (s == "-include") {
441  last = s;
442  continue;
443  }
444  if (last == "-include") {
445  if (s != "__clang_cuda_runtime_wrapper.h") {
446  cmd += " -include " + s;
447  }
448  last = s;
449  continue;
450  }
451 
452  // Using -ffcuda-is-device flag produces empty gpu module
453  if (s == "-fcuda-is-device") {
454  last = s;
455  continue;
456  }
457 
458  if constexpr (CLANG_VERSION_MAJOR == 9) {
459  if (clang_version_major > 9) {
460  // The following clang 9 flags are unknown to clang >9:
461  if (s == "-masm-verbose" || s == "-fuse-init-array" ||
462  s == "-dwarf-column-info" || s == "-momit-leaf-frame-pointer" ||
463  s == "-fdiagnostics-show-option" || s == "-mdisable-fp-elim") {
464  last = s;
465  continue;
466  }
467  if (s == "-fmessage-length") {
468  skip = 1;
469  last = s;
470  continue;
471  }
472  }
473  }
474 
475  if constexpr (CLANG_VERSION_MAJOR == 10) {
476  if (clang_version_major > 10) {
477  // The following clang 10 flags are unknown to clang >10:
478  if (s == "-masm-verbose" || s == "-dwarf-column-info" ||
479  s == "-fdiagnostics-show-option") {
480  last = s;
481  continue;
482  }
483  if (s == "-fmessage-length") {
484  skip = 1;
485  last = s;
486  continue;
487  }
488  }
489  }
490 
491  if constexpr (CLANG_VERSION_MAJOR >= 10) {
492  if (clang_version_major < 10) {
493  // The following clang >10 flags are unknown to clang <10:
494  if (s == "-fno-rounding-math" || s.rfind("-mframe-pointer=", 0) == 0 ||
495  s.rfind("-fgnuc-version=", 0) == 0) {
496  last = s;
497  continue;
498  }
499  }
500  }
501 
502  if constexpr (CLANG_VERSION_MAJOR == 11) {
503  if (clang_version_major < 11) {
504  // The following clang 11 flags are unknown to clang <11:
505  if (s == "-fno-verbose-asm") {
506  last = s;
507  continue;
508  }
509  if (s == "-aux-target-cpu") {
510  last = s;
511  skip = 1;
512  continue;
513  }
514  }
515  }
516 
517  cmd += " " + s;
518  last = s;
519  }
520  // TODO: Here we don't use the_driver->ExecuteCompilation because
521  // could not find a better way to modify driver arguments. As a
522  // workaround, we run clang compiler via pipe (it could be run
523  // also via shell).
524  exec_output(cmd);
525  return 0;
526  }
527 
528  llvm::SmallVector<std::pair<int, const driver::Command*>, 10> failing_commands;
529  int res = the_driver->ExecuteCompilation(*compilation, failing_commands);
530  if (res < 0) {
531  for (const std::pair<int, const driver::Command*>& p : failing_commands) {
532  if (p.first) {
533  the_driver->generateCompilationDiagnostics(*compilation, *p.second);
534  }
535  }
536  }
537  return res;
538 }
539 
540 #ifdef HAVE_CUDA
541 std::string UdfCompiler::compileToNVVMIR(const std::string& udf_file_name) const {
542  const auto gpu_out_filename = genNVVMIRFilename(udf_file_name);
543 
544  std::vector<std::string> command_line{clang_path_,
545  "-c",
546  "-O2",
547  "-emit-llvm",
548  "-o",
549  gpu_out_filename,
550  "-std=c++14",
551  "-DNO_BOOST"};
552 
553  command_line.emplace_back("--cuda-gpu-arch=" +
555  command_line.emplace_back("--cuda-device-only");
556  command_line.emplace_back("-xcuda");
557  command_line.emplace_back("--no-cuda-version-check");
558  const auto cuda_path = get_cuda_home();
559  if (cuda_path != "") {
560  command_line.emplace_back("--cuda-path=" + cuda_path);
561  }
562 
563  command_line.emplace_back(udf_file_name);
564 
565  // clean up from previous runs
566  boost::filesystem::remove(gpu_out_filename);
567  auto status = compileFromCommandLine(command_line);
568  // make sure that compilation actually succeeded by checking the
569  // output file:
570  if (!status && !boost::filesystem::exists(gpu_out_filename)) {
571  throw std::runtime_error(
572  "Failed to generate GPU UDF IR in CUDA mode with error code " +
573  std::to_string(status));
574  }
575  return gpu_out_filename;
576 }
577 #endif
578 
579 std::string UdfCompiler::compileToLLVMIR(const std::string& udf_file_name) const {
580  std::string cpu_out_filename = genLLVMIRFilename(udf_file_name);
581 
582  std::vector<std::string> command_line{clang_path_,
583  "-c",
584  "-O2",
585  "-emit-llvm",
586  "-o",
587  cpu_out_filename,
588  "-std=c++14",
589  "-DNO_BOOST",
590  udf_file_name};
591  auto res = compileFromCommandLine(command_line);
592  if (res != 0) {
593  throw std::runtime_error("Failed to compile CPU UDF (status code " +
594  std::to_string(res) + ")");
595  }
596  if (!boost::filesystem::exists(cpu_out_filename)) {
597  throw std::runtime_error("udf compile did not produce output file " +
598  cpu_out_filename);
599  }
600  return cpu_out_filename;
601 }
602 
603 void UdfCompiler::generateAST(const std::string& file_name) const {
604  UdfClangDriver the_driver = UdfClangDriver::init(clang_path_);
605  std::string resource_path = the_driver.getClangDriver()->ResourceDir;
606  std::string include_option =
607  std::string("-I") + resource_path + std::string("/include");
608 
609  std::vector<std::string> arg_vector;
610  arg_vector.emplace_back("astparser");
611  arg_vector.emplace_back(file_name);
612  arg_vector.emplace_back("--");
613  arg_vector.emplace_back("-DNO_BOOST");
614  arg_vector.emplace_back(include_option);
615 
616  if (clang_options_.size() > 0) {
617  std::copy(
618  clang_options_.begin(), clang_options_.end(), std::back_inserter(arg_vector));
619  }
620  std::vector<const char*> arg_vec2;
622  arg_vector.begin(), arg_vector.end(), std::back_inserter(arg_vec2), convert);
623 
624  int num_args = arg_vec2.size();
625 #if LLVM_VERSION_MAJOR > 12
626  auto op = CommonOptionsParser::create(num_args, &arg_vec2[0], ToolingSampleCategory);
627  ClangTool tool(op->getCompilations(), op->getSourcePathList());
628 #else
629  CommonOptionsParser op(num_args, &arg_vec2[0], ToolingSampleCategory);
630  ClangTool tool(op.getCompilations(), op.getSourcePathList());
631 #endif
632 
633  std::string out_name(file_name);
634  std::string file_ext("ast");
635  replace_extension(out_name, file_ext);
636 
637  std::error_code out_error_info;
638  llvm::raw_fd_ostream out_file(
639  llvm::StringRef(out_name), out_error_info, llvm::sys::fs::OF_None);
640 
641  auto factory = std::make_unique<ToolFactory>(out_file);
642  const auto result = tool.run(factory.get());
643  if (result != 0) {
644  throw std::runtime_error(
645  "Unable to create AST file for udf compilation (error code " +
646  std::to_string(result) + ")");
647  }
648 }
649 
650 std::string UdfCompiler::getAstFileName(const std::string& udf_file_name) {
651  auto ast_file_name = udf_file_name;
652  replace_extension(ast_file_name, "ast");
653  return ast_file_name;
654 }
std::unique_ptr< clang::DiagnosticConsumer > diag_client_owner
#define CHECK_EQ(x, y)
Definition: Logger.h:219
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &instance, StringRef file) override
std::vector< std::string > clang_options_
Definition: UdfCompiler.h:73
std::string getFuncDeclFileName(FunctionDecl *f) const
Definition: UdfCompiler.cpp:86
static std::string getAstFileName(const std::string &udf_file_name)
#define LOG(tag)
Definition: Logger.h:205
llvm::IntrusiveRefCntPtr< clang::DiagnosticIDs > diag_id
int compileFromCommandLine(const std::vector< std::string > &command_line) const
std::string get_clang_path(const std::string &clang_path_override)
bool HandleTopLevelDecl(DeclGroupRef decl_reference) override
std::string exec_output(std::string cmd)
FunctionDeclVisitor(llvm::raw_fd_ostream &ast_file, SourceManager &s_manager, ASTContext &context)
Definition: UdfCompiler.cpp:56
::FILE * popen(const char *command, const char *type)
Definition: omnisci_fs.cpp:76
std::tuple< int, int, int > get_clang_version(const std::string &clang_path)
std::string to_string(char const *&&v)
FILE * create(const std::string &basePath, const int fileId, const size_t pageSize, const size_t numPages)
Definition: File.cpp:51
std::string get_cuda_home(void)
Definition: CudaMgr.cpp:405
void generateAST(const std::string &file_name) const
void init(LogOptions const &log_opts)
Definition: Logger.cpp:305
DEVICE auto copy(ARGS &&...args)
Definition: gpu_enabled.h:51
int count
std::string remove_file_extension(const std::string &path)
OUTPUT transform(INPUT const &input, FUNC const &func)
Definition: misc.h:288
ToolFactory(llvm::raw_fd_ostream &ast_file)
static std::string deviceArchToSM(const NvidiaDeviceArch arch)
Definition: CudaMgr.h:148
void replace_extension(std::string &s, const std::string &new_ext)
llvm::IntrusiveRefCntPtr< clang::DiagnosticOptions > diag_options
UdfCompiler(CudaMgr_Namespace::NvidiaDeviceArch target_arch, const std::string &clang_path_override="")
static std::string genNVVMIRFilename(const std::string &udf_file_name)
#define CREATE_FRONTEND_ACTION(ast_file_)
int32_t pclose(::FILE *fh)
Definition: omnisci_fs.cpp:80
std::string compileToLLVMIR(const std::string &udf_file_name) const
static std::string genLLVMIRFilename(const std::string &udf_file_name)
std::string get_file_ext(const std::string &s)
char * f
std::pair< std::string, std::string > compileUdf(const std::string &udf_file_name) const
const char * convert(const std::string &s)
std::string clang_path_
Definition: UdfCompiler.h:72
std::tuple< int, int, int > getClangVersion() const
static llvm::cl::OptionCategory ToolingSampleCategory("UDF Tooling")
DeclASTConsumer(llvm::raw_fd_ostream &ast_file, SourceManager &s_manager, ASTContext &context)