---
 src/gallium/state_trackers/clover/api/dispatch.cpp |  2 +-
 src/gallium/state_trackers/clover/api/program.cpp  | 41 ++++++++++++++++++++--
 .../state_trackers/clover/core/compiler.hpp        | 11 +++---
 src/gallium/state_trackers/clover/core/program.cpp | 14 ++++++--
 src/gallium/state_trackers/clover/core/program.hpp |  5 ++-
 .../state_trackers/clover/llvm/invocation.cpp      | 33 +++++++++++++----
 6 files changed, 89 insertions(+), 17 deletions(-)

diff --git a/src/gallium/state_trackers/clover/api/dispatch.cpp 
b/src/gallium/state_trackers/clover/api/dispatch.cpp
index 35d150d..b5a4094 100644
--- a/src/gallium/state_trackers/clover/api/dispatch.cpp
+++ b/src/gallium/state_trackers/clover/api/dispatch.cpp
@@ -122,7 +122,7 @@ namespace clover {
       clReleaseDevice,
       clCreateImage,
       clCreateProgramWithBuiltInKernels,
-      NULL, // clCompileProgram
+      clCompileProgram,
       NULL, // clLinkProgram
       clUnloadPlatformCompiler,
       NULL, // clGetKernelArgInfo
diff --git a/src/gallium/state_trackers/clover/api/program.cpp 
b/src/gallium/state_trackers/clover/api/program.cpp
index b81ce69..b0a906e 100644
--- a/src/gallium/state_trackers/clover/api/program.cpp
+++ b/src/gallium/state_trackers/clover/api/program.cpp
@@ -153,13 +153,35 @@ clBuildProgram(cl_program d_prog, cl_uint num_devs,
                const cl_device_id *d_devs, const char *p_opts,
                void (*pfn_notify)(cl_program, void *),
                void *user_data) try {
+   return clCompileProgram(d_prog, num_devs, d_devs, p_opts,
+                           0, 0, 0,
+                           pfn_notify, user_data);
+
+} catch (error &e) {
+   return e.get();
+}
+
+CLOVER_API cl_int
+clCompileProgram(cl_program d_prog, cl_uint num_devs,
+                 const cl_device_id *d_devs, const char *p_opts,
+                 cl_uint num_headers, const cl_program *d_header_progs,
+                 const char **header_names,
+                 void (*pfn_notify)(cl_program, void *),
+                 void *user_data) try {
+
    auto &prog = obj(d_prog);
    auto devs = (d_devs ? objs(d_devs, num_devs) :
                 ref_vector<device>(prog.context().devices()));
    auto opts = (p_opts ? p_opts : "");
 
-   if (bool(num_devs) != bool(d_devs) ||
-       (!pfn_notify && user_data))
+   if (bool(num_devs) != bool(d_devs))
+      throw error(CL_INVALID_VALUE);
+
+   if (!pfn_notify && user_data)
+      throw error(CL_INVALID_VALUE);
+
+   if (bool(num_headers) != bool(header_names) ||
+       bool(num_headers) != bool(d_header_progs))
       throw error(CL_INVALID_VALUE);
 
    if (any_of([&](const device &dev) {
@@ -167,7 +189,20 @@ clBuildProgram(cl_program d_prog, cl_uint num_devs,
          }, devs))
       throw error(CL_INVALID_DEVICE);
 
-   prog.build(devs, opts);
+   std::map<const std::string, const std::string> headers;
+   for (unsigned int i = 0; i < num_headers; ++i) {
+      auto h_name = std::string(header_names[i]);
+      auto &h_prog = obj(d_header_progs[i]);
+
+      // The specs is unclear on what to do in that case,
+      // however it says that headers have to be with sources
+      if (!h_prog.has_source)
+         throw error(CL_INVALID_OPERATION);
+
+      headers.insert(make_pair(h_name, h_prog.source()));
+   }
+
+   prog.build(devs, opts, headers);
    return CL_SUCCESS;
 
 } catch (error &e) {
diff --git a/src/gallium/state_trackers/clover/core/compiler.hpp 
b/src/gallium/state_trackers/clover/core/compiler.hpp
index 6ef84d1..3b1d9fc 100644
--- a/src/gallium/state_trackers/clover/core/compiler.hpp
+++ b/src/gallium/state_trackers/clover/core/compiler.hpp
@@ -23,6 +23,8 @@
 #ifndef CLOVER_CORE_COMPILER_HPP
 #define CLOVER_CORE_COMPILER_HPP
 
+#include <map>
+
 #include "util/compat.hpp"
 #include "core/error.hpp"
 #include "core/module.hpp"
@@ -30,10 +32,11 @@
 
 namespace clover {
    module compile_program_llvm(const compat::string &source,
-                               pipe_shader_ir ir,
-                               const compat::string &target,
-                               const compat::string &opts,
-                               compat::string &r_log);
+                   const compat::vector<compat::pair<const char*>> &headers,
+                   pipe_shader_ir ir,
+                   const compat::string &target,
+                   const compat::string &opts,
+                   compat::string &r_log);
 
    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 e09c3aa..b0a0a25 100644
--- a/src/gallium/state_trackers/clover/core/program.cpp
+++ b/src/gallium/state_trackers/clover/core/program.cpp
@@ -41,7 +41,8 @@ program::program(clover::context &ctx,
 }
 
 void
-program::build(const ref_vector<device> &devs, const char *opts) {
+program::build(const ref_vector<device> &devs, const char *opts,
+               const string_map &headers) {
    if (has_source) {
       _devices = devs;
 
@@ -54,10 +55,19 @@ program::build(const ref_vector<device> &devs, const char 
*opts) {
 
          compat::string log;
 
+         compat::vector<compat::pair<const char*>> compat_headers;
+         for (auto &header : headers) {
+            compat::pair<const char*> h;
+            h.first = header.first.c_str();
+            h.second = header.second.c_str();
+            compat_headers.push_back(h);
+         }
+
          try {
             auto module = (dev.ir_format() == PIPE_SHADER_IR_TGSI ?
                            compile_program_tgsi(_source) :
-                           compile_program_llvm(_source, dev.ir_format(),
+                           compile_program_llvm(_source, compat_headers,
+                                                dev.ir_format(),
                                                 dev.ir_target(), 
build_opts(dev),
                                                 log));
             _binaries.insert({ &dev, module });
diff --git a/src/gallium/state_trackers/clover/core/program.hpp 
b/src/gallium/state_trackers/clover/core/program.hpp
index 1081454..f5a4214 100644
--- a/src/gallium/state_trackers/clover/core/program.hpp
+++ b/src/gallium/state_trackers/clover/core/program.hpp
@@ -29,6 +29,8 @@
 #include "core/context.hpp"
 #include "core/module.hpp"
 
+typedef std::map<const std::string, const std::string> string_map;
+
 namespace clover {
    class program : public ref_counter, public _cl_program {
    private:
@@ -46,7 +48,8 @@ namespace clover {
       program &
       operator=(const program &prog) = delete;
 
-      void build(const ref_vector<device> &devs, const char *opts);
+      void build(const ref_vector<device> &devs, const char *opts,
+                 const string_map &headers);
 
       const bool has_source;
       const std::string &source() const;
diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp 
b/src/gallium/state_trackers/clover/llvm/invocation.cpp
index 5d2efc4..2db59be 100644
--- a/src/gallium/state_trackers/clover/llvm/invocation.cpp
+++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp
@@ -118,6 +118,7 @@ namespace {
 
    llvm::Module *
    compile(llvm::LLVMContext &llvm_ctx, const std::string &source,
+           const compat::vector<compat::pair<const char*>> &headers,
            const std::string &name, const std::string &triple,
            const std::string &processor, const std::string &opts,
            clang::LangAS::Map& address_spaces, compat::string &r_log) {
@@ -214,6 +215,25 @@ namespace {
       c.getPreprocessorOpts().addRemappedFile(name,
                                       
llvm::MemoryBuffer::getMemBuffer(source));
 
+      if (headers.size() > 0) {
+         const std::string tmp_header_path = "/tmp/clover/";
+
+         c.getHeaderSearchOpts().AddPath(tmp_header_path,
+                                         clang::frontend::Angled,
+                                         false, false
+                                         #if HAVE_LLVM < 0x0303
+                                         , false
+                                         #endif
+                                         );
+
+        for (auto &header : headers) {
+           const std::string path = tmp_header_path + 
std::string(header.first);
+           c.getPreprocessorOpts().addRemappedFile(path,
+                             llvm::MemoryBuffer::getMemBuffer(header.second));
+        }
+      }
+
+
       // Setting this attribute tells clang to link this file before
       // performing any optimizations.  This is required so that
       // we can replace calls to the OpenCL C barrier() builtin
@@ -392,10 +412,11 @@ namespace {
 
 module
 clover::compile_program_llvm(const compat::string &source,
-                             enum pipe_shader_ir ir,
-                             const compat::string &target,
-                             const compat::string &opts,
-                             compat::string &r_log) {
+                  const compat::vector<compat::pair<const char*>> &headers,
+                  enum pipe_shader_ir ir,
+                  const compat::string &target,
+                  const compat::string &opts,
+                  compat::string &r_log) {
 
    std::vector<llvm::Function *> kernels;
    size_t processor_str_len = std::string(target.begin()).find_first_of("-");
@@ -408,8 +429,8 @@ clover::compile_program_llvm(const compat::string &source,
 
    // 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(llvm_ctx, source, "input.cl", triple, processor,
-                               opts, address_spaces, r_log);
+   llvm::Module *mod = compile(llvm_ctx, source, headers, "input.cl",
+                               triple, processor, opts, address_spaces, r_log);
 
    find_kernels(mod, kernels);
 
-- 
2.0.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to