20 #include <clang/AST/AST.h>
21 #include <clang/AST/ASTConsumer.h>
22 #include <clang/AST/RecursiveASTVisitor.h>
23 #include <clang/Driver/Compilation.h>
24 #include <clang/Driver/Driver.h>
25 #include <clang/Frontend/CompilerInstance.h>
26 #include <clang/Frontend/FrontendActions.h>
27 #include <clang/Frontend/TextDiagnosticPrinter.h>
28 #include <clang/Parse/ParseAST.h>
29 #include <clang/Tooling/CommonOptionsParser.h>
30 #include <clang/Tooling/Tooling.h>
31 #include <llvm/Support/Program.h>
32 #include <llvm/Support/raw_ostream.h>
33 #include <boost/process/search_path.hpp>
37 #if LLVM_VERSION_MAJOR >= 11
38 #include <llvm/Support/Host.h>
44 using namespace clang;
45 using namespace clang::tooling;
57 SourceManager& s_manager,
59 : ast_file_(ast_file), source_manager_(s_manager), context_(context) {
60 source_manager_.getDiagnostics().setShowColors(
false);
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);
82 auto f_entry = source_manager_.getFileEntryForID(source_manager_.getMainFileID());
83 return f_entry->getName().str();
87 SourceLocation spell_loc = source_manager_.getSpellingLoc(f->getLocation());
88 PresumedLoc p_loc = source_manager_.getPresumedLoc(spell_loc);
90 return std::string(p_loc.getFilename());
104 SourceManager& s_manager,
106 : visitor_(ast_file, s_manager, context) {}
111 for (DeclGroupRef::iterator b = decl_reference.begin(), e = decl_reference.end();
115 visitor_.TraverseDecl(*b);
132 StringRef file)
override {
133 return std::make_unique<DeclASTConsumer>(
134 ast_file_, instance.getSourceManager(), instance.getASTContext());
143 #if LLVM_VERSION_MAJOR >= 10
145 #define CREATE_FRONTEND_ACTION(ast_file_) std::make_unique<HandleDeclAction>(ast_file_)
148 #define CREATE_FRONTEND_ACTION(ast_file_) new HandleDeclAction(ast_file_)
151 ToolFactory(llvm::raw_fd_ostream& ast_file) : ast_file_(ast_file) {}
165 : diag_options(new DiagnosticOptions())
166 , diag_client(new TextDiagnosticPrinter(llvm::errs(), diag_options.get()))
167 , diag_id(new clang::DiagnosticIDs())
168 , diags(diag_id, diag_options.get(), diag_client)
169 , diag_client_owner(diags.takeClient())
170 , the_driver(clang_path.c_str(), llvm::sys::getDefaultTargetTriple(), diags) {}
173 if (path ==
"." || path ==
"..") {
177 size_t pos = path.find_last_of(
"\\/.");
178 if (pos != std::string::npos && path[pos] ==
'.') {
179 return path.substr(0, pos);
186 size_t i = s.rfind(
'.', s.length());
187 if (1 != std::string::npos) {
188 return (s.substr(i + 1, s.length() -
i));
193 std::string::size_type
i = s.rfind(
'.', s.length());
195 if (i != std::string::npos) {
196 s.replace(i + 1,
getFileExt(s).length(), new_ext);
203 gpu_file_name +=
"_gpu.bc";
204 return gpu_file_name;
210 cpu_file_name +=
"_cpu.bc";
211 return cpu_file_name;
218 std::vector<const char*> clang_command_opts;
219 clang_command_opts.reserve(command_line.size() +
clang_options_.size());
221 std::transform(std::begin(command_line),
222 std::end(command_line),
223 std::back_inserter(clang_command_opts),
224 [&](
const std::string& str) {
return str.c_str(); });
230 std::back_inserter(clang_command_opts),
231 [&](
const std::string& str) {
return str.c_str(); });
234 the_driver->CCPrintOptions = 0;
235 std::unique_ptr<driver::Compilation> compilation(
236 the_driver->BuildCompilation(clang_command_opts));
239 LOG(
FATAL) <<
"failed to build compilation object!\n";
242 llvm::SmallVector<std::pair<int, const driver::Command*>, 10> failing_commands;
243 int res = the_driver->ExecuteCompilation(*compilation, failing_commands);
245 for (
const std::pair<int, const driver::Command*>& p : failing_commands) {
247 the_driver->generateCompilationDiagnostics(*compilation, *p.second);
272 command_line.emplace_back(
"--cuda-gpu-arch=" +
274 command_line.emplace_back(
"--cuda-device-only");
275 command_line.emplace_back(
"-xcuda");
276 command_line.emplace_back(
"--no-cuda-version-check");
278 if (cuda_path !=
"") {
279 command_line.emplace_back(
"--cuda-path=" + cuda_path);
284 command_line.emplace_back(udf_file_name);
287 boost::filesystem::remove(gpu_out_filename);
291 if (!status && !boost::filesystem::exists(gpu_out_filename)) {
314 std::string resource_path = the_driver.
getClangDriver()->ResourceDir;
315 std::string include_option =
316 std::string(
"-I") + resource_path + std::string(
"/include");
318 std::vector<std::string> arg_vector;
319 arg_vector.emplace_back(
"astparser");
320 arg_vector.emplace_back(file_name);
321 arg_vector.emplace_back(
"--");
322 arg_vector.emplace_back(
"-DNO_BOOST");
323 arg_vector.emplace_back(include_option);
330 std::vector<const char*> arg_vec2;
332 arg_vector.begin(), arg_vector.end(), std::back_inserter(arg_vec2),
convert);
334 int num_args = arg_vec2.size();
336 ClangTool tool(op.getCompilations(), op.getSourcePathList());
338 std::string out_name(file_name);
339 std::string file_ext(
"ast");
342 std::error_code out_error_info;
343 llvm::raw_fd_ostream out_file(
344 llvm::StringRef(out_name), out_error_info, llvm::sys::fs::F_None);
346 auto factory = std::make_unique<ToolFactory>(out_file);
347 return tool.run(factory.get());
357 if (clang_path.empty()) {
358 clang_path_.assign(llvm::sys::findProgramByName(
"clang++").
get());
360 throw std::runtime_error(
361 "Unable to find clang++ to compile user defined functions");
366 if (!boost::filesystem::exists(clang_path)) {
367 throw std::runtime_error(
"Path provided for udf compiler " + clang_path +
371 if (boost::filesystem::is_directory(clang_path)) {
372 throw std::runtime_error(
"Path provided for udf compiler " + clang_path +
373 " is not to the clang++ executable.");
380 const std::string& clang_path)
381 : udf_file_name_(file_name)
382 , udf_ast_file_name_(file_name)
383 , target_arch_(target_arch) {
389 const std::string& clang_path,
390 const std::vector<std::string> clang_options)
391 : udf_file_name_(file_name)
392 , udf_ast_file_name_(file_name)
393 , target_arch_(target_arch)
394 , clang_options_(clang_options) {
401 VLOG(1) <<
"UDFCompiler cpu bc file = " << cpu_ir_file;
409 VLOG(1) <<
"UDFCompiler gpu bc file = " << gpu_ir_file;
420 int gpu_compile_result = 1;
434 if (gpu_compile_result != 0) {
438 return gpu_compile_result;
450 if (ast_result == 0) {
455 int gpu_compile_result = 1;
458 if (cpu_compile_result == 0) {
462 if (gpu_compile_result == 0) {
465 LOG(
FATAL) <<
"Unable to compile UDF file for gpu";
470 LOG(
FATAL) <<
"Unable to compile UDF file for cpu";
474 LOG(
FATAL) <<
"Unable to create AST file for udf compilation";
clang::driver::Driver * getClangDriver()
std::string genCpuIrFilename(const char *udf_file_name)
int compileToCpuByteCode(const char *udf_file_name)
void readCompiledModules()
std::vector< std::string > clang_options_
bool VisitFunctionDecl(FunctionDecl *f)
UdfCompiler(const std::string &udf_file_name, CudaMgr_Namespace::NvidiaDeviceArch target_arch, const std::string &clang_path="")
std::string getMainFileName() const
const std::string & getAstFileName() const
void readCpuCompiledModule()
void read_udf_cpu_module(const std::string &udf_ir_filename)
static llvm::cl::OptionCategory ToolingSampleCategory("UDF Tooling")
void read_udf_gpu_module(const std::string &udf_ir_filename)
External interface for parsing AST and bitcode files.
llvm::raw_fd_ostream & ast_file_
std::string genGpuIrFilename(const char *udf_file_name)
const char * convert(const std::string &s)
std::string removeFileExtension(const std::string &path)
HandleDeclAction(llvm::raw_fd_ostream &ast_file)
DeclASTConsumer(llvm::raw_fd_ostream &ast_file, SourceManager &s_manager, ASTContext &context)
int compileToGpuByteCode(const char *udf_file_name, bool cpu_mode)
std::string get_cuda_home(void)
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &instance, StringRef file) override
DEVICE auto copy(ARGS &&...args)
std::string udf_ast_file_name_
FunctionDeclVisitor visitor_
SourceManager & source_manager_
~HandleDeclAction() override
llvm::raw_fd_ostream & ast_file_
UdfClangDriver(const std::string &)
int parseToAst(const char *file_name)
bool HandleTopLevelDecl(DeclGroupRef decl_reference) override
CudaMgr_Namespace::NvidiaDeviceArch target_arch_
static std::string deviceArchToSM(const NvidiaDeviceArch arch)
void init(const std::string &clang_path)
std::string udf_file_name_
void replaceExtn(std::string &s, const std::string &new_ext)
std::string getFuncDeclFileName(FunctionDecl *f) const
void readGpuCompiledModule()
std::string getFileExt(std::string &s)
FunctionDeclVisitor(llvm::raw_fd_ostream &ast_file, SourceManager &s_manager, ASTContext &context)
int compileFromCommandLine(const std::vector< std::string > &command_line)
#define CREATE_FRONTEND_ACTION(ast_file_)