From c68babfc3c7b65dd53697528781bd6b6186f5190 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Tue, 27 Nov 2012 21:57:15 +0000 Subject: [PATCH] clover: Add support for compiler flags Reviewed-by: Francisco Jerez --- .../state_trackers/clover/api/program.cpp | 7 ++- .../state_trackers/clover/core/compiler.hpp | 12 ++++- .../state_trackers/clover/core/program.cpp | 12 +++-- .../state_trackers/clover/core/program.hpp | 3 +- .../state_trackers/clover/llvm/invocation.cpp | 49 +++++++++++++++++-- 5 files changed, 71 insertions(+), 12 deletions(-) diff --git a/src/gallium/state_trackers/clover/api/program.cpp b/src/gallium/state_trackers/clover/api/program.cpp index 74de840d3df..06f96f1845c 100644 --- a/src/gallium/state_trackers/clover/api/program.cpp +++ b/src/gallium/state_trackers/clover/api/program.cpp @@ -142,15 +142,18 @@ clBuildProgram(cl_program prog, cl_uint count, const cl_device_id *devs, (!pfn_notify && user_data)) throw error(CL_INVALID_VALUE); + if (!opts) + opts = ""; + if (devs) { if (any_of([&](const cl_device_id dev) { return !prog->ctx.has_device(dev); }, devs, devs + count)) throw error(CL_INVALID_DEVICE); - prog->build({ devs, devs + count }); + prog->build({ devs, devs + count }, opts); } else { - prog->build(prog->ctx.devs); + prog->build(prog->ctx.devs, opts); } return CL_SUCCESS; diff --git a/src/gallium/state_trackers/clover/core/compiler.hpp b/src/gallium/state_trackers/clover/core/compiler.hpp index a43050a22a3..38695073709 100644 --- a/src/gallium/state_trackers/clover/core/compiler.hpp +++ b/src/gallium/state_trackers/clover/core/compiler.hpp @@ -44,9 +44,19 @@ namespace clover { compat::vector log; }; + class invalid_option_error { + public: + invalid_option_error() { + } + + virtual ~invalid_option_error() { + } + }; + module compile_program_llvm(const compat::string &source, enum pipe_shader_ir ir, - const compat::string &target); + const compat::string &target, + const compat::string &opts); module compile_program_tgsi(const compat::string &source); } diff --git a/src/gallium/state_trackers/clover/core/program.cpp b/src/gallium/state_trackers/clover/core/program.cpp index 5fcda23fc65..92f1d6f5aa5 100644 --- a/src/gallium/state_trackers/clover/core/program.cpp +++ b/src/gallium/state_trackers/clover/core/program.cpp @@ -41,21 +41,27 @@ _cl_program::_cl_program(clover::context &ctx, } void -_cl_program::build(const std::vector &devs) { +_cl_program::build(const std::vector &devs, + const char *opts) { for (auto dev : devs) { __binaries.erase(dev); __logs.erase(dev); + __opts.erase(dev); + + __opts.insert({ dev, opts }); try { auto module = (dev->ir_format() == PIPE_SHADER_IR_TGSI ? compile_program_tgsi(__source) : compile_program_llvm(__source, dev->ir_format(), - dev->ir_target())); + dev->ir_target(), build_opts(dev))); __binaries.insert({ dev, module }); } catch (build_error &e) { __logs.insert({ dev, e.what() }); throw error(CL_BUILD_PROGRAM_FAILURE); + } catch (invalid_option_error &e) { + throw error(CL_INVALID_BUILD_OPTIONS); } } } @@ -77,7 +83,7 @@ _cl_program::build_status(clover::device *dev) const { std::string _cl_program::build_opts(clover::device *dev) const { - return {}; + return __opts.count(dev) ? __opts.find(dev)->second : ""; } std::string diff --git a/src/gallium/state_trackers/clover/core/program.hpp b/src/gallium/state_trackers/clover/core/program.hpp index f3858f6ce98..0cda8eeceb3 100644 --- a/src/gallium/state_trackers/clover/core/program.hpp +++ b/src/gallium/state_trackers/clover/core/program.hpp @@ -41,7 +41,7 @@ public: const std::vector &devs, const std::vector &binaries); - void build(const std::vector &devs); + void build(const std::vector &devs, const char *opts); const std::string &source() const; const std::map &binaries() const; @@ -55,6 +55,7 @@ public: private: std::map __binaries; std::map __logs; + std::map __opts; std::string __source; }; diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp index 2b07053ba20..c9973679a4c 100644 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp @@ -23,6 +23,7 @@ #include "core/compiler.hpp" #include +#include #include #include #include @@ -51,6 +52,7 @@ #include #include #include +#include using namespace clover; @@ -98,15 +100,49 @@ namespace { llvm::Module * compile(const std::string &source, const std::string &name, - const std::string &triple) { + const std::string &triple, const std::string &opts) { clang::CompilerInstance c; + clang::CompilerInvocation invocation; clang::EmitLLVMOnlyAction act(&llvm::getGlobalContext()); std::string log; llvm::raw_string_ostream s_log(log); - c.getFrontendOpts().Inputs.push_back( - clang::FrontendInputFile(name, clang::IK_OpenCL)); + // Parse the compiler options: + std::vector opts_array; + std::istringstream ss(opts); + + while (!ss.eof()) { + std::string opt; + getline(ss, opt, ' '); + opts_array.push_back(opt); + } + + opts_array.push_back(name); + + std::vector opts_carray; + for (unsigned i = 0; i < opts_array.size(); i++) { + opts_carray.push_back(opts_array.at(i).c_str()); + } + + llvm::IntrusiveRefCntPtr DiagID; + llvm::IntrusiveRefCntPtr DiagOpts; + clang::TextDiagnosticBuffer *DiagsBuffer; + + DiagID = new clang::DiagnosticIDs(); + DiagOpts = new clang::DiagnosticOptions(); + DiagsBuffer = new clang::TextDiagnosticBuffer(); + + clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); + bool Success; + + Success = clang::CompilerInvocation::CreateFromArgs(c.getInvocation(), + opts_carray.data(), + opts_carray.data() + opts_carray.size(), + Diags); + if (!Success) { + throw invalid_option_error(); + } c.getFrontendOpts().ProgramAction = clang::frontend::EmitLLVMOnly; c.getHeaderSearchOpts().UseBuiltinIncludes = true; c.getHeaderSearchOpts().UseStandardSystemIncludes = true; @@ -271,11 +307,14 @@ namespace { module clover::compile_program_llvm(const compat::string &source, enum pipe_shader_ir ir, - const compat::string &triple) { + const compat::string &triple, + const compat::string &opts) { std::vector kernels; - llvm::Module *mod = compile(source, "cl_input", triple); + // The input file name must have the .cl extension in order for the + // CompilerInvocation class to recognize it as an OpenCL source file. + llvm::Module *mod = compile(source, "input.cl", triple, opts); find_kernels(mod, kernels);