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