clover: Add initial implementation of clCompileProgram for CL 1.2.
authorEdB <edb+mesa@sigluy.net>
Mon, 20 Oct 2014 07:34:17 +0000 (10:34 +0300)
committerFrancisco Jerez <currojerez@riseup.net>
Mon, 20 Oct 2014 07:34:51 +0000 (10:34 +0300)
[ Francisco Jerez: General clean-up. ]

Reviewed-by: Francisco Jerez <currojerez@riseup.net>
src/gallium/state_trackers/clover/api/dispatch.cpp
src/gallium/state_trackers/clover/api/program.cpp
src/gallium/state_trackers/clover/core/compiler.hpp
src/gallium/state_trackers/clover/core/error.hpp
src/gallium/state_trackers/clover/core/program.cpp
src/gallium/state_trackers/clover/core/program.hpp
src/gallium/state_trackers/clover/llvm/invocation.cpp

index 35d150d6dc896f3692a623d3a402c70c89204357..b5a4094cf2fe1a4bf67fe4a60da774b938314836 100644 (file)
@@ -122,7 +122,7 @@ namespace clover {
       clReleaseDevice,
       clCreateImage,
       clCreateProgramWithBuiltInKernels,
-      NULL, // clCompileProgram
+      clCompileProgram,
       NULL, // clLinkProgram
       clUnloadPlatformCompiler,
       NULL, // clGetKernelArgInfo
index 67717353a8cca0c9f5aa2ef8abfa96fc3887a15c..342915be1e206d7b6fdf112ac642792ac0aa932f 100644 (file)
@@ -152,14 +152,30 @@ CLOVER_API cl_int
 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 {
+               void *user_data) {
+   cl_int ret = clCompileProgram(d_prog, num_devs, d_devs, p_opts,
+                                 0, NULL, NULL, pfn_notify, user_data);
+
+   return (ret == CL_COMPILE_PROGRAM_FAILURE ?
+           CL_BUILD_PROGRAM_FAILURE : ret);
+}
+
+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 : "");
+   header_map headers;
 
    if (bool(num_devs) != bool(d_devs) ||
-       (!pfn_notify && user_data))
+       (!pfn_notify && user_data) ||
+       bool(num_headers) != bool(header_names))
       throw error(CL_INVALID_VALUE);
 
    if (any_of([&](const device &dev) {
@@ -167,10 +183,23 @@ clBuildProgram(cl_program d_prog, cl_uint num_devs,
          }, devs))
       throw error(CL_INVALID_DEVICE);
 
-   if (prog.kernel_ref_count())
+   if (prog.kernel_ref_count() ||
+       !prog.has_source)
       throw error(CL_INVALID_OPERATION);
 
-   prog.build(devs, opts);
+
+   for_each([&](const char *name, const program &header) {
+         if (!header.has_source)
+            throw error(CL_INVALID_OPERATION);
+
+         if (!any_of(key_equals(name), headers))
+            headers.push_back(compat::pair<compat::string, compat::string>(
+                                 name, header.source()));
+      },
+      range(header_names, num_headers),
+      objs(d_header_progs, num_headers));
+
+   prog.build(devs, opts, headers);
    return CL_SUCCESS;
 
 } catch (error &e) {
index 6ef84d1c0d84403af332b374c559088b6fd316aa..7210d1e9cdc5ac17a3d9b422d6f876d9555de37c 100644 (file)
 #include "pipe/p_defines.h"
 
 namespace clover {
+   typedef compat::vector<compat::pair<compat::string,
+                                       compat::string> > header_map;
+
    module compile_program_llvm(const compat::string &source,
+                               const header_map &headers,
                                pipe_shader_ir ir,
                                const compat::string &target,
                                const compat::string &opts,
index cecbe9b110e45de05ca1a0acedc25b924aacf8b4..7b010f1b1dd0f8310a0663c6924e6d22d8c71c88 100644 (file)
@@ -67,7 +67,7 @@ namespace clover {
    class build_error : public error {
    public:
       build_error(const compat::string &what = "") :
-         error(CL_BUILD_PROGRAM_FAILURE, what) {
+         error(CL_COMPILE_PROGRAM_FAILURE, what) {
       }
    };
 
index 6c224dbe083c677d990c5b94d7dec44f36ea25e9..8553ca7ec96c37104597ce2c7372e1787e89f100 100644 (file)
@@ -21,7 +21,6 @@
 //
 
 #include "core/program.hpp"
-#include "core/compiler.hpp"
 
 using namespace clover;
 
@@ -41,7 +40,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 header_map &headers) {
    if (has_source) {
       _devices = devs;
 
@@ -57,7 +57,8 @@ program::build(const ref_vector<device> &devs, const char *opts) {
          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, headers,
+                                                dev.ir_format(),
                                                 dev.ir_target(), build_opts(dev),
                                                 log));
             _binaries.insert({ &dev, module });
index 4bb5b680d4ede3ee8d7a1e5e5d70d06b4ffe1b20..b5aae7e0dff7cdd3bc9993382557fbb3e20d0da6 100644 (file)
@@ -28,6 +28,7 @@
 #include "core/object.hpp"
 #include "core/context.hpp"
 #include "core/module.hpp"
+#include "core/compiler.hpp"
 
 namespace clover {
    class program : public ref_counter, public _cl_program {
@@ -46,7 +47,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 header_map &headers);
 
       const bool has_source;
       const std::string &source() const;
index 3cdf883e403432abb9410bca20a127a853740179..507daa0e3768da0e58524300b0e44791127f001f 100644 (file)
@@ -146,10 +146,11 @@ namespace {
 
    llvm::Module *
    compile_llvm(llvm::LLVMContext &llvm_ctx, const std::string &source,
-           const std::string &name, const std::string &triple,
-           const std::string &processor, const std::string &opts,
-           clang::LangAS::Map& address_spaces, unsigned &optimization_level,
-          compat::string &r_log) {
+                const header_map &headers,
+                const std::string &name, const std::string &triple,
+                const std::string &processor, const std::string &opts,
+                clang::LangAS::Map& address_spaces, unsigned &optimization_level,
+                compat::string &r_log) {
 
       clang::CompilerInstance c;
       clang::EmitLLVMOnlyAction act(&llvm_ctx);
@@ -248,6 +249,29 @@ namespace {
                                       llvm::MemoryBuffer::getMemBuffer(source));
 #endif
 
+      if (headers.size()) {
+         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 (header_map::const_iterator it = headers.begin();
+              it != headers.end(); ++it) {
+            const std::string path = tmp_header_path + std::string(it->first);
+            c.getPreprocessorOpts().addRemappedFile(path,
+#if HAVE_LLVM >= 0x0306
+                    llvm::MemoryBuffer::getMemBuffer(it->second.c_str()).release());
+#else
+                    llvm::MemoryBuffer::getMemBuffer(it->second.c_str()));
+#endif
+         }
+      }
+
       // 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
@@ -684,6 +708,7 @@ static const struct debug_named_value debug_options[] = {
 
 module
 clover::compile_program_llvm(const compat::string &source,
+                             const header_map &headers,
                              enum pipe_shader_ir ir,
                              const compat::string &target,
                              const compat::string &opts,
@@ -708,8 +733,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(llvm_ctx, source, "input.cl", triple,
-                                    processor, opts, address_spaces,
+   llvm::Module *mod = compile_llvm(llvm_ctx, source, headers, "input.cl",
+                                    triple, processor, opts, address_spaces,
                                     optimization_level, r_log);
 
    find_kernels(mod, kernels);