Re: [Mesa-dev] [PATCH 1/2] clover: Implement image attribute getters

2015-06-10 Thread Zoltán Gilián
 Whether you need to pass the image
 dimensions and data type to the kernel as explicit parameters or not
 (e.g. because your hardware already supports some sort of image metadata
 query opcode) is driver-specific, so it would probably be a better idea
 to append these parameters at the end of the input buffer in the r600
 pipe driver itself.

The image data type and channel order get converted to a pipe format value
in clover before it reaches the driver, so either the driver needs to
convert it back to OpenCL constants, or clover has to send the data
explicitly to the pipe e.g. by appending it to the kernel parameters. What
solution do you think is less problematic? Are there better mechanisms to
send the image data type and channel order in OpenCL format to the pipe?

Furthermore IIRC the pipe has no explicit information on the number of
image arguments, so it would have to gather that information to determine
the amount of input memory needed by the kernel. Clover has that
information easily accessible.

How bad would it be if image attributes were handled similarly to grid
dimension and grid offset? The get_image_* builtins could be lowered to
implicit parameter reads, so there is no need to perform the llvm pass.

On Tue, Jun 9, 2015 at 11:09 AM, Zoltán Gilián zoltan.gil...@gmail.com
wrote:

 Ok, thanks for the feedback.

 On Mon, Jun 8, 2015 at 2:18 PM, Francisco Jerez curroje...@riseup.net
 wrote:

 Zoltan Gilian zoltan.gil...@gmail.com writes:

  Image attributes are passed to the kernel as hidden parameters after the
  image attribute itself. An llvm pass replaces the getter builtins to
  the appropriate parameters.
  ---
   src/gallium/state_trackers/clover/core/kernel.cpp  |  13 ++
   src/gallium/state_trackers/clover/core/memory.cpp  |   2 +-
   .../state_trackers/clover/llvm/invocation.cpp  | 158
 -
   3 files changed, 170 insertions(+), 3 deletions(-)
 
  diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp
 b/src/gallium/state_trackers/clover/core/kernel.cpp
  index 0756f06..4703899 100644
  --- a/src/gallium/state_trackers/clover/core/kernel.cpp
  +++ b/src/gallium/state_trackers/clover/core/kernel.cpp
  @@ -483,6 +483,19 @@ kernel::image_rd_argument::bind(exec_context ctx,
  align(ctx.input, marg.target_align);
  insert(ctx.input, v);
 
  +   cl_image_format fmt = img-format();
  +   cl_uint image_attribs[] = {img-width(), img-height(),
 img-depth(),
  +  fmt.image_channel_data_type,
  +  fmt.image_channel_order};
  +   for (int i = 0; i  5; i++) {
  +  auto v = bytes(image_attribs[i]);
  +
  +  extend(v, module::argument::zero_ext, marg.target_size);
  +  byteswap(v, ctx.q-device().endianness());
  +  align(ctx.input, marg.target_align);
  +  insert(ctx.input, v);
  +   }
  +
 This seems to be implementing driver-specific policy in a
 hardware-independent state tracker.  Whether you need to pass the image
 dimensions and data type to the kernel as explicit parameters or not
 (e.g. because your hardware already supports some sort of image metadata
 query opcode) is driver-specific, so it would probably be a better idea
 to append these parameters at the end of the input buffer in the r600
 pipe driver itself.

  st = img-resource(*ctx.q).bind_sampler_view(*ctx.q);
  ctx.sviews.push_back(st);
   }
  diff --git a/src/gallium/state_trackers/clover/core/memory.cpp
 b/src/gallium/state_trackers/clover/core/memory.cpp
  index 055336a..b852e68 100644
  --- a/src/gallium/state_trackers/clover/core/memory.cpp
  +++ b/src/gallium/state_trackers/clover/core/memory.cpp
  @@ -189,7 +189,7 @@ image2d::image2d(clover::context ctx, cl_mem_flags
 flags,
const cl_image_format *format, size_t width,
size_t height, size_t row_pitch,
void *host_ptr) :
  -   image(ctx, flags, format, width, height, 0,
  +   image(ctx, flags, format, width, height, 1,
row_pitch, 0, height * row_pitch, host_ptr) {
   }
 
  diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp
 b/src/gallium/state_trackers/clover/llvm/invocation.cpp
  index 9b91fee..5d5e619 100644
  --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp
  +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp
  @@ -33,6 +33,8 @@
   #include llvm/IR/DiagnosticInfo.h
   #include llvm/IR/DiagnosticPrinter.h
   #include llvm/IR/DerivedTypes.h
  +#include llvm/IR/InstIterator.h
  +#include llvm/IR/Instructions.h
   #include llvm/IR/LLVMContext.h
   #include llvm/IR/Module.h
   #include llvm/Support/SourceMgr.h
  @@ -80,6 +82,130 @@
   using namespace clover;
 
   namespace {
  +
  +   /* LLVM pass to resolve get_image_* OpenCL builtins.
  +* The image attributes (e.g. width or channel order) are passed as
 hidden
  +* arguments to the kernel.
  +* This pass replaces specific function calls with the appropriate
 hidden
  +* arguments. 

Re: [Mesa-dev] [PATCH 1/2] clover: Implement image attribute getters

2015-06-10 Thread Francisco Jerez
Zoltán Gilián zoltan.gil...@gmail.com writes:

 Whether you need to pass the image
 dimensions and data type to the kernel as explicit parameters or not
 (e.g. because your hardware already supports some sort of image metadata
 query opcode) is driver-specific, so it would probably be a better idea
 to append these parameters at the end of the input buffer in the r600
 pipe driver itself.

 The image data type and channel order get converted to a pipe format value
 in clover before it reaches the driver, so either the driver needs to
 convert it back to OpenCL constants, or clover has to send the data
 explicitly to the pipe e.g. by appending it to the kernel parameters. What
 solution do you think is less problematic? Are there better mechanisms to
 send the image data type and channel order in OpenCL format to the pipe?

Both approaches you mention sound reasonable to me, as long as either
the pipe driver or LLVM back-end has control on whether and how these
implicit arguments are passed to the kernel.


 Furthermore IIRC the pipe has no explicit information on the number of
 image arguments, so it would have to gather that information to determine
 the amount of input memory needed by the kernel. Clover has that
 information easily accessible.

Yes, the pipe driver would have to assume that all images bound to the
pipeline may be used by the kernel, and make all their metadata
accessible to the kernel in some hardware-dependent manner (surface
metadata query opcode, implicit constant buffer, implicit arguments,
etc.).


 How bad would it be if image attributes were handled similarly to grid
 dimension and grid offset? The get_image_* builtins could be lowered to
 implicit parameter reads, so there is no need to perform the llvm pass.

The grid dimension and offset handling we have right now is a hack, it's
done that way because we're missing some target-independent mechanism
(e.g ELF metadata section) for the back-end to provide Clover
information about the implicit arguments it wants.  I guess it's OK if
you use the same approach as grid arguments for now, but we'll
definitely need a better solution for the long term.

 On Tue, Jun 9, 2015 at 11:09 AM, Zoltán Gilián zoltan.gil...@gmail.com
 wrote:

 Ok, thanks for the feedback.

 On Mon, Jun 8, 2015 at 2:18 PM, Francisco Jerez curroje...@riseup.net
 wrote:

 Zoltan Gilian zoltan.gil...@gmail.com writes:

  Image attributes are passed to the kernel as hidden parameters after the
  image attribute itself. An llvm pass replaces the getter builtins to
  the appropriate parameters.
  ---
   src/gallium/state_trackers/clover/core/kernel.cpp  |  13 ++
   src/gallium/state_trackers/clover/core/memory.cpp  |   2 +-
   .../state_trackers/clover/llvm/invocation.cpp  | 158
 -
   3 files changed, 170 insertions(+), 3 deletions(-)
 
  diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp
 b/src/gallium/state_trackers/clover/core/kernel.cpp
  index 0756f06..4703899 100644
  --- a/src/gallium/state_trackers/clover/core/kernel.cpp
  +++ b/src/gallium/state_trackers/clover/core/kernel.cpp
  @@ -483,6 +483,19 @@ kernel::image_rd_argument::bind(exec_context ctx,
  align(ctx.input, marg.target_align);
  insert(ctx.input, v);
 
  +   cl_image_format fmt = img-format();
  +   cl_uint image_attribs[] = {img-width(), img-height(),
 img-depth(),
  +  fmt.image_channel_data_type,
  +  fmt.image_channel_order};
  +   for (int i = 0; i  5; i++) {
  +  auto v = bytes(image_attribs[i]);
  +
  +  extend(v, module::argument::zero_ext, marg.target_size);
  +  byteswap(v, ctx.q-device().endianness());
  +  align(ctx.input, marg.target_align);
  +  insert(ctx.input, v);
  +   }
  +
 This seems to be implementing driver-specific policy in a
 hardware-independent state tracker.  Whether you need to pass the image
 dimensions and data type to the kernel as explicit parameters or not
 (e.g. because your hardware already supports some sort of image metadata
 query opcode) is driver-specific, so it would probably be a better idea
 to append these parameters at the end of the input buffer in the r600
 pipe driver itself.

  st = img-resource(*ctx.q).bind_sampler_view(*ctx.q);
  ctx.sviews.push_back(st);
   }
  diff --git a/src/gallium/state_trackers/clover/core/memory.cpp
 b/src/gallium/state_trackers/clover/core/memory.cpp
  index 055336a..b852e68 100644
  --- a/src/gallium/state_trackers/clover/core/memory.cpp
  +++ b/src/gallium/state_trackers/clover/core/memory.cpp
  @@ -189,7 +189,7 @@ image2d::image2d(clover::context ctx, cl_mem_flags
 flags,
const cl_image_format *format, size_t width,
size_t height, size_t row_pitch,
void *host_ptr) :
  -   image(ctx, flags, format, width, height, 0,
  +   image(ctx, flags, format, width, height, 1,
row_pitch, 0, height * row_pitch, host_ptr) {
   }
 
  diff 

Re: [Mesa-dev] [PATCH 1/2] clover: Implement image attribute getters

2015-06-09 Thread Zoltán Gilián
Ok, thanks for the feedback.

On Mon, Jun 8, 2015 at 2:18 PM, Francisco Jerez curroje...@riseup.net
wrote:

 Zoltan Gilian zoltan.gil...@gmail.com writes:

  Image attributes are passed to the kernel as hidden parameters after the
  image attribute itself. An llvm pass replaces the getter builtins to
  the appropriate parameters.
  ---
   src/gallium/state_trackers/clover/core/kernel.cpp  |  13 ++
   src/gallium/state_trackers/clover/core/memory.cpp  |   2 +-
   .../state_trackers/clover/llvm/invocation.cpp  | 158
 -
   3 files changed, 170 insertions(+), 3 deletions(-)
 
  diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp
 b/src/gallium/state_trackers/clover/core/kernel.cpp
  index 0756f06..4703899 100644
  --- a/src/gallium/state_trackers/clover/core/kernel.cpp
  +++ b/src/gallium/state_trackers/clover/core/kernel.cpp
  @@ -483,6 +483,19 @@ kernel::image_rd_argument::bind(exec_context ctx,
  align(ctx.input, marg.target_align);
  insert(ctx.input, v);
 
  +   cl_image_format fmt = img-format();
  +   cl_uint image_attribs[] = {img-width(), img-height(), img-depth(),
  +  fmt.image_channel_data_type,
  +  fmt.image_channel_order};
  +   for (int i = 0; i  5; i++) {
  +  auto v = bytes(image_attribs[i]);
  +
  +  extend(v, module::argument::zero_ext, marg.target_size);
  +  byteswap(v, ctx.q-device().endianness());
  +  align(ctx.input, marg.target_align);
  +  insert(ctx.input, v);
  +   }
  +
 This seems to be implementing driver-specific policy in a
 hardware-independent state tracker.  Whether you need to pass the image
 dimensions and data type to the kernel as explicit parameters or not
 (e.g. because your hardware already supports some sort of image metadata
 query opcode) is driver-specific, so it would probably be a better idea
 to append these parameters at the end of the input buffer in the r600
 pipe driver itself.

  st = img-resource(*ctx.q).bind_sampler_view(*ctx.q);
  ctx.sviews.push_back(st);
   }
  diff --git a/src/gallium/state_trackers/clover/core/memory.cpp
 b/src/gallium/state_trackers/clover/core/memory.cpp
  index 055336a..b852e68 100644
  --- a/src/gallium/state_trackers/clover/core/memory.cpp
  +++ b/src/gallium/state_trackers/clover/core/memory.cpp
  @@ -189,7 +189,7 @@ image2d::image2d(clover::context ctx, cl_mem_flags
 flags,
const cl_image_format *format, size_t width,
size_t height, size_t row_pitch,
void *host_ptr) :
  -   image(ctx, flags, format, width, height, 0,
  +   image(ctx, flags, format, width, height, 1,
row_pitch, 0, height * row_pitch, host_ptr) {
   }
 
  diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp
 b/src/gallium/state_trackers/clover/llvm/invocation.cpp
  index 9b91fee..5d5e619 100644
  --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp
  +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp
  @@ -33,6 +33,8 @@
   #include llvm/IR/DiagnosticInfo.h
   #include llvm/IR/DiagnosticPrinter.h
   #include llvm/IR/DerivedTypes.h
  +#include llvm/IR/InstIterator.h
  +#include llvm/IR/Instructions.h
   #include llvm/IR/LLVMContext.h
   #include llvm/IR/Module.h
   #include llvm/Support/SourceMgr.h
  @@ -80,6 +82,130 @@
   using namespace clover;
 
   namespace {
  +
  +   /* LLVM pass to resolve get_image_* OpenCL builtins.
  +* The image attributes (e.g. width or channel order) are passed as
 hidden
  +* arguments to the kernel.
  +* This pass replaces specific function calls with the appropriate
 hidden
  +* arguments. The libclc library needs to implements the get_image_*
  +* builtins as these specific functions to avoid dealing with name
 mangling
  +* here.
  +*/
  +   struct OpenCLImageBuiltinPass : public llvm::FunctionPass {
  +  static char ID;
  +
  +  OpenCLImageBuiltinPass(): llvm::FunctionPass(ID) {}
  +  bool runOnFunction(llvm::Function F) override;
  +
  +  struct ImageAttribArgs {
  + ImageAttribArgs(): image_arg(0),
  +width_arg(0),
  +heigth_arg(0),
  +depth_arg(0),
  +channel_data_type_arg(0),
  +channel_order_arg(0) {}
  + llvm::Argument* image_arg;
  + llvm::Argument* width_arg;
  + llvm::Argument* heigth_arg;
  + llvm::Argument* depth_arg;
  + llvm::Argument* channel_data_type_arg;
  + llvm::Argument* channel_order_arg;
  +  };
  +   };
  +
  +   char OpenCLImageBuiltinPass::ID = 0;
  +
  +   bool
  +   OpenCLImageBuiltinPass::runOnFunction(llvm::Function F)
  +   {
  +  llvm::Module* mod = F.getParent();
  +  llvm::DataLayout TD(mod);
  +  llvm::Type* cl_int_type =
  + TD.getSmallestLegalIntType(mod-getContext(), sizeof(cl_int));
  +
  +  

[Mesa-dev] [PATCH 1/2] clover: Implement image attribute getters

2015-06-08 Thread Zoltan Gilian
Image attributes are passed to the kernel as hidden parameters after the
image attribute itself. An llvm pass replaces the getter builtins to
the appropriate parameters.
---
 src/gallium/state_trackers/clover/core/kernel.cpp  |  13 ++
 src/gallium/state_trackers/clover/core/memory.cpp  |   2 +-
 .../state_trackers/clover/llvm/invocation.cpp  | 158 -
 3 files changed, 170 insertions(+), 3 deletions(-)

diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp 
b/src/gallium/state_trackers/clover/core/kernel.cpp
index 0756f06..4703899 100644
--- a/src/gallium/state_trackers/clover/core/kernel.cpp
+++ b/src/gallium/state_trackers/clover/core/kernel.cpp
@@ -483,6 +483,19 @@ kernel::image_rd_argument::bind(exec_context ctx,
align(ctx.input, marg.target_align);
insert(ctx.input, v);
 
+   cl_image_format fmt = img-format();
+   cl_uint image_attribs[] = {img-width(), img-height(), img-depth(),
+  fmt.image_channel_data_type,
+  fmt.image_channel_order};
+   for (int i = 0; i  5; i++) {
+  auto v = bytes(image_attribs[i]);
+
+  extend(v, module::argument::zero_ext, marg.target_size);
+  byteswap(v, ctx.q-device().endianness());
+  align(ctx.input, marg.target_align);
+  insert(ctx.input, v);
+   }
+
st = img-resource(*ctx.q).bind_sampler_view(*ctx.q);
ctx.sviews.push_back(st);
 }
diff --git a/src/gallium/state_trackers/clover/core/memory.cpp 
b/src/gallium/state_trackers/clover/core/memory.cpp
index 055336a..b852e68 100644
--- a/src/gallium/state_trackers/clover/core/memory.cpp
+++ b/src/gallium/state_trackers/clover/core/memory.cpp
@@ -189,7 +189,7 @@ image2d::image2d(clover::context ctx, cl_mem_flags flags,
  const cl_image_format *format, size_t width,
  size_t height, size_t row_pitch,
  void *host_ptr) :
-   image(ctx, flags, format, width, height, 0,
+   image(ctx, flags, format, width, height, 1,
  row_pitch, 0, height * row_pitch, host_ptr) {
 }
 
diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp 
b/src/gallium/state_trackers/clover/llvm/invocation.cpp
index 9b91fee..5d5e619 100644
--- a/src/gallium/state_trackers/clover/llvm/invocation.cpp
+++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp
@@ -33,6 +33,8 @@
 #include llvm/IR/DiagnosticInfo.h
 #include llvm/IR/DiagnosticPrinter.h
 #include llvm/IR/DerivedTypes.h
+#include llvm/IR/InstIterator.h
+#include llvm/IR/Instructions.h
 #include llvm/IR/LLVMContext.h
 #include llvm/IR/Module.h
 #include llvm/Support/SourceMgr.h
@@ -80,6 +82,130 @@
 using namespace clover;
 
 namespace {
+
+   /* LLVM pass to resolve get_image_* OpenCL builtins.
+* The image attributes (e.g. width or channel order) are passed as hidden
+* arguments to the kernel.
+* This pass replaces specific function calls with the appropriate hidden
+* arguments. The libclc library needs to implements the get_image_*
+* builtins as these specific functions to avoid dealing with name mangling
+* here.
+*/
+   struct OpenCLImageBuiltinPass : public llvm::FunctionPass {
+  static char ID;
+
+  OpenCLImageBuiltinPass(): llvm::FunctionPass(ID) {}
+  bool runOnFunction(llvm::Function F) override;
+
+  struct ImageAttribArgs {
+ ImageAttribArgs(): image_arg(0),
+width_arg(0),
+heigth_arg(0),
+depth_arg(0),
+channel_data_type_arg(0),
+channel_order_arg(0) {}
+ llvm::Argument* image_arg;
+ llvm::Argument* width_arg;
+ llvm::Argument* heigth_arg;
+ llvm::Argument* depth_arg;
+ llvm::Argument* channel_data_type_arg;
+ llvm::Argument* channel_order_arg;
+  };
+   };
+
+   char OpenCLImageBuiltinPass::ID = 0;
+
+   bool
+   OpenCLImageBuiltinPass::runOnFunction(llvm::Function F)
+   {
+  llvm::Module* mod = F.getParent();
+  llvm::DataLayout TD(mod);
+  llvm::Type* cl_int_type =
+ TD.getSmallestLegalIntType(mod-getContext(), sizeof(cl_int));
+
+  std::vectorImageAttribArgs img_args;
+  for (auto arg = F.arg_begin(), E = F.arg_end(); arg != E; ++arg) {
+
+ llvm::Type *arg_type = arg-getType();
+ if (!arg_type-isPointerTy()) continue;
+
+ llvm::Type *elem_type = arg_type-getPointerElementType();
+ if (!elem_type-isStructTy()) continue;
+
+ const llvm::StringRef type_name = elem_type-getStructName();
+ if (!type_name.startswith(opencl.image2d_t)) continue;
+
+ auto name_suffix = llvm::Twine(img_args.size());
+ ImageAttribArgs attrib_args;
+ attrib_args.image_arg = arg;
+ attrib_args.width_arg = new llvm::Argument(
+cl_int_type, image_width + name_suffix);
+ attrib_args.heigth_arg = new llvm::Argument(
+cl_int_type, image_height + 

Re: [Mesa-dev] [PATCH 1/2] clover: Implement image attribute getters

2015-06-08 Thread Francisco Jerez
Zoltan Gilian zoltan.gil...@gmail.com writes:

 Image attributes are passed to the kernel as hidden parameters after the
 image attribute itself. An llvm pass replaces the getter builtins to
 the appropriate parameters.
 ---
  src/gallium/state_trackers/clover/core/kernel.cpp  |  13 ++
  src/gallium/state_trackers/clover/core/memory.cpp  |   2 +-
  .../state_trackers/clover/llvm/invocation.cpp  | 158 
 -
  3 files changed, 170 insertions(+), 3 deletions(-)

 diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp 
 b/src/gallium/state_trackers/clover/core/kernel.cpp
 index 0756f06..4703899 100644
 --- a/src/gallium/state_trackers/clover/core/kernel.cpp
 +++ b/src/gallium/state_trackers/clover/core/kernel.cpp
 @@ -483,6 +483,19 @@ kernel::image_rd_argument::bind(exec_context ctx,
 align(ctx.input, marg.target_align);
 insert(ctx.input, v);
  
 +   cl_image_format fmt = img-format();
 +   cl_uint image_attribs[] = {img-width(), img-height(), img-depth(),
 +  fmt.image_channel_data_type,
 +  fmt.image_channel_order};
 +   for (int i = 0; i  5; i++) {
 +  auto v = bytes(image_attribs[i]);
 +
 +  extend(v, module::argument::zero_ext, marg.target_size);
 +  byteswap(v, ctx.q-device().endianness());
 +  align(ctx.input, marg.target_align);
 +  insert(ctx.input, v);
 +   }
 +
This seems to be implementing driver-specific policy in a
hardware-independent state tracker.  Whether you need to pass the image
dimensions and data type to the kernel as explicit parameters or not
(e.g. because your hardware already supports some sort of image metadata
query opcode) is driver-specific, so it would probably be a better idea
to append these parameters at the end of the input buffer in the r600
pipe driver itself.

 st = img-resource(*ctx.q).bind_sampler_view(*ctx.q);
 ctx.sviews.push_back(st);
  }
 diff --git a/src/gallium/state_trackers/clover/core/memory.cpp 
 b/src/gallium/state_trackers/clover/core/memory.cpp
 index 055336a..b852e68 100644
 --- a/src/gallium/state_trackers/clover/core/memory.cpp
 +++ b/src/gallium/state_trackers/clover/core/memory.cpp
 @@ -189,7 +189,7 @@ image2d::image2d(clover::context ctx, cl_mem_flags flags,
   const cl_image_format *format, size_t width,
   size_t height, size_t row_pitch,
   void *host_ptr) :
 -   image(ctx, flags, format, width, height, 0,
 +   image(ctx, flags, format, width, height, 1,
   row_pitch, 0, height * row_pitch, host_ptr) {
  }
  
 diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp 
 b/src/gallium/state_trackers/clover/llvm/invocation.cpp
 index 9b91fee..5d5e619 100644
 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp
 +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp
 @@ -33,6 +33,8 @@
  #include llvm/IR/DiagnosticInfo.h
  #include llvm/IR/DiagnosticPrinter.h
  #include llvm/IR/DerivedTypes.h
 +#include llvm/IR/InstIterator.h
 +#include llvm/IR/Instructions.h
  #include llvm/IR/LLVMContext.h
  #include llvm/IR/Module.h
  #include llvm/Support/SourceMgr.h
 @@ -80,6 +82,130 @@
  using namespace clover;
  
  namespace {
 +
 +   /* LLVM pass to resolve get_image_* OpenCL builtins.
 +* The image attributes (e.g. width or channel order) are passed as hidden
 +* arguments to the kernel.
 +* This pass replaces specific function calls with the appropriate hidden
 +* arguments. The libclc library needs to implements the get_image_*
 +* builtins as these specific functions to avoid dealing with name 
 mangling
 +* here.
 +*/
 +   struct OpenCLImageBuiltinPass : public llvm::FunctionPass {
 +  static char ID;
 +
 +  OpenCLImageBuiltinPass(): llvm::FunctionPass(ID) {}
 +  bool runOnFunction(llvm::Function F) override;
 +
 +  struct ImageAttribArgs {
 + ImageAttribArgs(): image_arg(0),
 +width_arg(0),
 +heigth_arg(0),
 +depth_arg(0),
 +channel_data_type_arg(0),
 +channel_order_arg(0) {}
 + llvm::Argument* image_arg;
 + llvm::Argument* width_arg;
 + llvm::Argument* heigth_arg;
 + llvm::Argument* depth_arg;
 + llvm::Argument* channel_data_type_arg;
 + llvm::Argument* channel_order_arg;
 +  };
 +   };
 +
 +   char OpenCLImageBuiltinPass::ID = 0;
 +
 +   bool
 +   OpenCLImageBuiltinPass::runOnFunction(llvm::Function F)
 +   {
 +  llvm::Module* mod = F.getParent();
 +  llvm::DataLayout TD(mod);
 +  llvm::Type* cl_int_type =
 + TD.getSmallestLegalIntType(mod-getContext(), sizeof(cl_int));
 +
 +  std::vectorImageAttribArgs img_args;
 +  for (auto arg = F.arg_begin(), E = F.arg_end(); arg != E; ++arg) {
 +
 + llvm::Type *arg_type = arg-getType();
 + if (!arg_type-isPointerTy()) continue;
 +
 +