include/ChangeLog:
authorUlrich Weigand <uweigand@de.ibm.com>
Tue, 8 Feb 2011 13:30:10 +0000 (13:30 +0000)
committerUlrich Weigand <uweigand@de.ibm.com>
Tue, 8 Feb 2011 13:30:10 +0000 (13:30 +0000)
* dwarf2.h (enum dwarf_calling_convention): Add DW_CC_GDB_IBM_OpenCL.

gdb/ChangeLog:

* dwarf2read.c (read_subroutine_type): Set special calling
convention flag for functions compiled by IBM XL C for OpenCL.
* ppc-sysv-tdep.c: Include "dwarf2.h"
(ppc_sysv_abi_push_dummy_call): Implement IBM OpenCL vector types
calling convention.
(do_ppc_sysv_return_value): Add FUNC_TYPE argument.  Implement
IBM OpenCL vector types calling convention.
(ppc_sysv_abi_return_value): Pass through FUNC_TYPE.
(ppc_sysv_abi_broken_return_value): Likewise.
(ppc64_sysv_abi_push_dummy_call): Implement IBM OpenCL vector
types calling convention.
(ppc64_sysv_abi_return_value): Likewise.
* spu-tdep.c: Include "dwarf2.h"
(spu_return_value): Implement IBM OpenCL vector types calling
convention.

gdb/testsuite/ChangeLog:

* gdb.opencl/callfuncs.cl: New file.
* gdb.opencl/callfuncs.exp: New test.
* gdb.opencl/Makefile.in (EXECUTABLES): Add callfuncs.

gdb/ChangeLog
gdb/dwarf2read.c
gdb/ppc-sysv-tdep.c
gdb/spu-tdep.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.opencl/Makefile.in
gdb/testsuite/gdb.opencl/callfuncs.cl [new file with mode: 0644]
gdb/testsuite/gdb.opencl/callfuncs.exp [new file with mode: 0644]
include/ChangeLog
include/dwarf2.h

index 0197e8bce1dcc2115da1c437e1e015dddc0817e4..87f31f341b9a8b6461e1946417aed2c7bdd8b2dd 100644 (file)
@@ -1,3 +1,21 @@
+2011-02-08  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * dwarf2read.c (read_subroutine_type): Set special calling
+       convention flag for functions compiled by IBM XL C for OpenCL.
+       * ppc-sysv-tdep.c: Include "dwarf2.h"
+       (ppc_sysv_abi_push_dummy_call): Implement IBM OpenCL vector types
+       calling convention.
+       (do_ppc_sysv_return_value): Add FUNC_TYPE argument.  Implement
+       IBM OpenCL vector types calling convention.
+       (ppc_sysv_abi_return_value): Pass through FUNC_TYPE.
+       (ppc_sysv_abi_broken_return_value): Likewise.
+       (ppc64_sysv_abi_push_dummy_call): Implement IBM OpenCL vector
+       types calling convention.
+       (ppc64_sysv_abi_return_value): Likewise.
+       * spu-tdep.c: Include "dwarf2.h"
+       (spu_return_value): Implement IBM OpenCL vector types calling
+       convention.
+
 2011-02-08  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call): Implement
index f269deebc47ca00176d41a83ff6e5fec0bd27800..837fa3bc6f7e10dc3895bb1ef4f270b8df6f12fa 100644 (file)
@@ -7955,7 +7955,12 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
      the subroutine die.  Otherwise set the calling convention to
      the default value DW_CC_normal.  */
   attr = dwarf2_attr (die, DW_AT_calling_convention, cu);
-  TYPE_CALLING_CONVENTION (ftype) = attr ? DW_UNSND (attr) : DW_CC_normal;
+  if (attr)
+    TYPE_CALLING_CONVENTION (ftype) = DW_UNSND (attr);
+  else if (cu->producer && strstr (cu->producer, "IBM XL C for OpenCL"))
+    TYPE_CALLING_CONVENTION (ftype) = DW_CC_GDB_IBM_OpenCL;
+  else
+    TYPE_CALLING_CONVENTION (ftype) = DW_CC_normal;
 
   /* We need to add the subroutine type to the die immediately so
      we don't infinitely recurse when dealing with parameters
index 300dcac6f1f685e665ce39e1c50c38109b0a2d9c..872117df31932b2229187220ba9348ef12590f69 100644 (file)
@@ -30,6 +30,7 @@
 #include "target.h"
 #include "objfiles.h"
 #include "infcall.h"
+#include "dwarf2.h"
 
 /* Pass the arguments in either registers, or in the stack.  Using the
    ppc sysv ABI, the first eight words of the argument list (that might
@@ -50,6 +51,8 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  struct type *ftype;
+  int opencl_abi = 0;
   ULONGEST saved_sp;
   int argspace = 0;            /* 0 is an initial wrong guess.  */
   int write_pass;
@@ -59,6 +62,13 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   regcache_cooked_read_unsigned (regcache, gdbarch_sp_regnum (gdbarch),
                                 &saved_sp);
 
+  ftype = check_typedef (value_type (function));
+  if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
+    ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
+  if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
+      && TYPE_CALLING_CONVENTION (ftype) == DW_CC_GDB_IBM_OpenCL)
+    opencl_abi = 1;
+
   /* Go through the argument list twice.
 
      Pass 1: Figure out how much new stack space is required for
@@ -327,6 +337,126 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                 Hence we increase freg even when writing to memory.  */
              freg += 2;
            }
+         else if (len < 16
+                  && TYPE_CODE (type) == TYPE_CODE_ARRAY
+                  && TYPE_VECTOR (type)
+                  && opencl_abi)
+           {
+             /* OpenCL vectors shorter than 16 bytes are passed as if
+                a series of independent scalars.  */
+             struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type));
+             int i, nelt = TYPE_LENGTH (type) / TYPE_LENGTH (eltype);
+
+             for (i = 0; i < nelt; i++)
+               {
+                 const gdb_byte *elval = val + i * TYPE_LENGTH (eltype);
+
+                 if (TYPE_CODE (eltype) == TYPE_CODE_FLT && !tdep->soft_float)
+                   {
+                     if (freg <= 8)
+                       {
+                         if (write_pass)
+                           {
+                             int regnum = tdep->ppc_fp0_regnum + freg;
+                             gdb_byte regval[MAX_REGISTER_SIZE];
+                             struct type *regtype
+                               = register_type (gdbarch, regnum);
+                             convert_typed_floating (elval, eltype,
+                                                     regval, regtype);
+                             regcache_cooked_write (regcache, regnum, regval);
+                           }
+                         freg++;
+                       }
+                     else
+                       {
+                         argoffset = align_up (argoffset, len);
+                         if (write_pass)
+                           write_memory (sp + argoffset, val, len);
+                         argoffset += len;
+                       }
+                   }
+                 else if (TYPE_LENGTH (eltype) == 8)
+                   {
+                     if (greg > 9)
+                       {
+                         /* Just in case GREG was 10.  */
+                         greg = 11;
+                         argoffset = align_up (argoffset, 8);
+                         if (write_pass)
+                           write_memory (sp + argoffset, elval,
+                                         TYPE_LENGTH (eltype));
+                         argoffset += 8;
+                       }
+                     else
+                       {
+                         /* Must start on an odd register - r3/r4 etc.  */
+                         if ((greg & 1) == 0)
+                           greg++;
+                         if (write_pass)
+                           {
+                             int regnum = tdep->ppc_gp0_regnum + greg;
+                             regcache_cooked_write (regcache,
+                                                    regnum + 0, elval + 0);
+                             regcache_cooked_write (regcache,
+                                                    regnum + 1, elval + 4);
+                           }
+                         greg += 2;
+                       }
+                   }
+                 else
+                   {
+                     gdb_byte word[MAX_REGISTER_SIZE];
+                     store_unsigned_integer (word, tdep->wordsize, byte_order,
+                                             unpack_long (eltype, elval));
+
+                     if (greg <= 10)
+                       {
+                         if (write_pass)
+                           regcache_cooked_write (regcache,
+                                                  tdep->ppc_gp0_regnum + greg,
+                                                  word);
+                         greg++;
+                       }
+                     else
+                       {
+                         argoffset = align_up (argoffset, tdep->wordsize);
+                         if (write_pass)
+                           write_memory (sp + argoffset, word, tdep->wordsize);
+                         argoffset += tdep->wordsize;
+                       }
+                   }
+               }
+           }
+         else if (len >= 16
+                  && TYPE_CODE (type) == TYPE_CODE_ARRAY
+                  && TYPE_VECTOR (type)
+                  && opencl_abi)
+           {
+             /* OpenCL vectors 16 bytes or longer are passed as if
+                a series of AltiVec vectors.  */
+             int i;
+
+             for (i = 0; i < len / 16; i++)
+               {
+                 const gdb_byte *elval = val + i * 16;
+
+                 if (vreg <= 13)
+                   {
+                     if (write_pass)
+                       regcache_cooked_write (regcache,
+                                              tdep->ppc_vr0_regnum + vreg,
+                                              elval);
+                     vreg++;
+                   }
+                 else
+                   {
+                     argoffset = align_up (argoffset, 16);
+                     if (write_pass)
+                       write_memory (sp + argoffset, elval, 16);
+                     argoffset += 16;
+                   }
+               }
+           }
          else if (len == 16
                   && TYPE_CODE (type) == TYPE_CODE_ARRAY
                   && TYPE_VECTOR (type)
@@ -552,13 +682,21 @@ get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype,
    when returned in general-purpose registers.  */
 
 static enum return_value_convention
-do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
-                         struct regcache *regcache, gdb_byte *readbuf,
-                         const gdb_byte *writebuf, int broken_gcc)
+do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
+                         struct type *type, struct regcache *regcache,
+                         gdb_byte *readbuf, const gdb_byte *writebuf,
+                         int broken_gcc)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int opencl_abi = 0;
+
+  if (func_type
+      && TYPE_CALLING_CONVENTION (func_type) == DW_CC_GDB_IBM_OpenCL)
+    opencl_abi = 1;
+
   gdb_assert (tdep->wordsize == 4);
+
   if (TYPE_CODE (type) == TYPE_CODE_FLT
       && TYPE_LENGTH (type) <= 8
       && !tdep->soft_float)
@@ -691,6 +829,83 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
+  /* OpenCL vectors < 16 bytes are returned as distinct
+     scalars in f1..f2 or r3..r10.  */
+  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+      && TYPE_VECTOR (type)
+      && TYPE_LENGTH (type) < 16
+      && opencl_abi)
+    {
+      struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type));
+      int i, nelt = TYPE_LENGTH (type) / TYPE_LENGTH (eltype);
+
+      for (i = 0; i < nelt; i++)
+       {
+         int offset = i * TYPE_LENGTH (eltype);
+
+         if (TYPE_CODE (eltype) == TYPE_CODE_FLT)
+           {
+             int regnum = tdep->ppc_fp0_regnum + 1 + i;
+             gdb_byte regval[MAX_REGISTER_SIZE];
+             struct type *regtype = register_type (gdbarch, regnum);
+
+             if (writebuf != NULL)
+               {
+                 convert_typed_floating (writebuf + offset, eltype,
+                                         regval, regtype);
+                 regcache_cooked_write (regcache, regnum, regval);
+               }
+             if (readbuf != NULL)
+               {
+                 regcache_cooked_read (regcache, regnum, regval);
+                 convert_typed_floating (regval, regtype,
+                                         readbuf + offset, eltype);
+               }
+           }
+         else
+           {
+             int regnum = tdep->ppc_gp0_regnum + 3 + i;
+             ULONGEST regval;
+
+             if (writebuf != NULL)
+               {
+                 regval = unpack_long (eltype, writebuf + offset);
+                 regcache_cooked_write_unsigned (regcache, regnum, regval);
+               }
+             if (readbuf != NULL)
+               {
+                 regcache_cooked_read_unsigned (regcache, regnum, &regval);
+                 store_unsigned_integer (readbuf + offset,
+                                         TYPE_LENGTH (eltype), byte_order,
+                                         regval);
+               }
+           }
+       }
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+  /* OpenCL vectors >= 16 bytes are returned in v2..v9.  */
+  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+      && TYPE_VECTOR (type)
+      && TYPE_LENGTH (type) >= 16
+      && opencl_abi)
+    {
+      int n_regs = TYPE_LENGTH (type) / 16;
+      int i;
+
+      for (i = 0; i < n_regs; i++)
+       {
+         int offset = i * 16;
+         int regnum = tdep->ppc_vr0_regnum + 2 + i;
+
+         if (writebuf != NULL)
+           regcache_cooked_write (regcache, regnum, writebuf + offset);
+         if (readbuf != NULL)
+           regcache_cooked_read (regcache, regnum, readbuf + offset);
+       }
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
   if (TYPE_LENGTH (type) == 16
       && TYPE_CODE (type) == TYPE_CODE_ARRAY
       && TYPE_VECTOR (type)
@@ -826,8 +1041,8 @@ ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type,
                           struct type *valtype, struct regcache *regcache,
                           gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  return do_ppc_sysv_return_value (gdbarch, valtype, regcache, readbuf,
-                                  writebuf, 0);
+  return do_ppc_sysv_return_value (gdbarch, func_type, valtype, regcache,
+                                  readbuf, writebuf, 0);
 }
 
 enum return_value_convention
@@ -837,8 +1052,8 @@ ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch,
                                  struct regcache *regcache,
                                  gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  return do_ppc_sysv_return_value (gdbarch, valtype, regcache, readbuf,
-                                  writebuf, 1);
+  return do_ppc_sysv_return_value (gdbarch, func_type, valtype, regcache,
+                                  readbuf, writebuf, 1);
 }
 
 /* The helper function for 64-bit SYSV push_dummy_call.  Converts the
@@ -899,6 +1114,8 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
   CORE_ADDR func_addr = find_function_addr (function, NULL);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  struct type *ftype;
+  int opencl_abi = 0;
   ULONGEST back_chain;
   /* See for-loop comment below.  */
   int write_pass;
@@ -925,6 +1142,13 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
   regcache_cooked_read_unsigned (regcache, gdbarch_sp_regnum (gdbarch),
                                 &back_chain);
 
+  ftype = check_typedef (value_type (function));
+  if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
+    ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
+  if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
+      && TYPE_CALLING_CONVENTION (ftype) == DW_CC_GDB_IBM_OpenCL)
+    opencl_abi = 1;
+
   /* Go through the argument list twice.
 
      Pass 1: Compute the function call's stack space and register
@@ -1133,6 +1357,109 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
              greg += 2;
              gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
            }
+         else if (TYPE_LENGTH (type) < 16
+                  && TYPE_CODE (type) == TYPE_CODE_ARRAY
+                  && TYPE_VECTOR (type)
+                  && opencl_abi)
+           {
+             /* OpenCL vectors shorter than 16 bytes are passed as if
+                a series of independent scalars.  */
+             struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type));
+             int i, nelt = TYPE_LENGTH (type) / TYPE_LENGTH (eltype);
+
+             for (i = 0; i < nelt; i++)
+               {
+                 const gdb_byte *elval = val + i * TYPE_LENGTH (eltype);
+
+                 if (TYPE_CODE (eltype) == TYPE_CODE_FLT)
+                   {
+                     if (write_pass)
+                       {
+                         gdb_byte regval[MAX_REGISTER_SIZE];
+                         const gdb_byte *p;
+
+                         if (TYPE_LENGTH (eltype) == 4)
+                           {
+                             memcpy (regval, elval, 4);
+                             memcpy (regval + 4, elval, 4);
+                             p = regval;
+                           }
+                         else
+                           p = elval;
+
+                         write_memory (gparam, p, 8);
+
+                         if (freg <= 13)
+                           {
+                             int regnum = tdep->ppc_fp0_regnum + freg;
+                             struct type *regtype
+                               = register_type (gdbarch, regnum);
+
+                             convert_typed_floating (elval, eltype,
+                                                     regval, regtype);
+                             regcache_cooked_write (regcache, regnum, regval);
+                           }
+
+                         if (greg <= 10)
+                           regcache_cooked_write (regcache,
+                                                  tdep->ppc_gp0_regnum + greg,
+                                                  regval);
+                       }
+
+                     freg++;
+                     greg++;
+                     gparam = align_up (gparam + 8, tdep->wordsize);
+                   }
+                 else
+                   {
+                     if (write_pass)
+                       {
+                         ULONGEST word = unpack_long (eltype, elval);
+                         if (greg <= 10)
+                           regcache_cooked_write_unsigned
+                             (regcache, tdep->ppc_gp0_regnum + greg, word);
+
+                         write_memory_unsigned_integer
+                           (gparam, tdep->wordsize, byte_order, word);
+                       }
+
+                     greg++;
+                     gparam = align_up (gparam + TYPE_LENGTH (eltype),
+                                        tdep->wordsize);
+                   }
+               }
+           }
+         else if (TYPE_LENGTH (type) >= 16
+                  && TYPE_CODE (type) == TYPE_CODE_ARRAY
+                  && TYPE_VECTOR (type)
+                  && opencl_abi)
+           {
+             /* OpenCL vectors 16 bytes or longer are passed as if
+                a series of AltiVec vectors.  */
+             int i;
+
+             for (i = 0; i < TYPE_LENGTH (type) / 16; i++)
+               {
+                 const gdb_byte *elval = val + i * 16;
+
+                 gparam = align_up (gparam, 16);
+                 greg += greg & 1;
+
+                 if (write_pass)
+                   {
+                     if (vreg <= 13)
+                       regcache_cooked_write (regcache,
+                                              tdep->ppc_vr0_regnum + vreg,
+                                              elval);
+
+                     write_memory (gparam, elval, 16);
+                   }
+
+                 greg += 2;
+                 vreg++;
+                 gparam += 16;
+               }
+           }
          else if (TYPE_LENGTH (type) == 16 && TYPE_VECTOR (type)
                   && TYPE_CODE (type) == TYPE_CODE_ARRAY
                   && tdep->ppc_vr0_regnum >= 0)
@@ -1358,6 +1685,11 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int opencl_abi = 0;
+
+  if (func_type
+      && TYPE_CALLING_CONVENTION (func_type) == DW_CC_GDB_IBM_OpenCL)
+    opencl_abi = 1;
 
   /* This function exists to support a calling convention that
      requires floating-point registers.  It shouldn't be used on
@@ -1420,6 +1752,83 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type,
        regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, readbuf);
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
+  /* OpenCL vectors < 16 bytes are returned as distinct
+     scalars in f1..f2 or r3..r10.  */
+  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
+      && TYPE_VECTOR (valtype)
+      && TYPE_LENGTH (valtype) < 16
+      && opencl_abi)
+    {
+      struct type *eltype = check_typedef (TYPE_TARGET_TYPE (valtype));
+      int i, nelt = TYPE_LENGTH (valtype) / TYPE_LENGTH (eltype);
+
+      for (i = 0; i < nelt; i++)
+       {
+         int offset = i * TYPE_LENGTH (eltype);
+
+         if (TYPE_CODE (eltype) == TYPE_CODE_FLT)
+           {
+             int regnum = tdep->ppc_fp0_regnum + 1 + i;
+             gdb_byte regval[MAX_REGISTER_SIZE];
+             struct type *regtype = register_type (gdbarch, regnum);
+
+             if (writebuf != NULL)
+               {
+                 convert_typed_floating (writebuf + offset, eltype,
+                                         regval, regtype);
+                 regcache_cooked_write (regcache, regnum, regval);
+               }
+             if (readbuf != NULL)
+               {
+                 regcache_cooked_read (regcache, regnum, regval);
+                 convert_typed_floating (regval, regtype,
+                                         readbuf + offset, eltype);
+               }
+           }
+         else
+           {
+             int regnum = tdep->ppc_gp0_regnum + 3 + i;
+             ULONGEST regval;
+
+             if (writebuf != NULL)
+               {
+                 regval = unpack_long (eltype, writebuf + offset);
+                 regcache_cooked_write_unsigned (regcache, regnum, regval);
+               }
+             if (readbuf != NULL)
+               {
+                 regcache_cooked_read_unsigned (regcache, regnum, &regval);
+                 store_unsigned_integer (readbuf + offset,
+                                         TYPE_LENGTH (eltype), byte_order,
+                                         regval);
+               }
+           }
+       }
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+  /* OpenCL vectors >= 16 bytes are returned in v2..v9.  */
+  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
+      && TYPE_VECTOR (valtype)
+      && TYPE_LENGTH (valtype) >= 16
+      && opencl_abi)
+    {
+      int n_regs = TYPE_LENGTH (valtype) / 16;
+      int i;
+
+      for (i = 0; i < n_regs; i++)
+       {
+         int offset = i * 16;
+         int regnum = tdep->ppc_vr0_regnum + 2 + i;
+
+         if (writebuf != NULL)
+           regcache_cooked_write (regcache, regnum, writebuf + offset);
+         if (readbuf != NULL)
+           regcache_cooked_read (regcache, regnum, readbuf + offset);
+       }
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
   /* Array type has more than one use.  */
   if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
     {
index d42465986884defb5bddab2a739a6ff15f68679c..0b0ea4ee60ff0342e647eed584ca6027f0f59576 100644 (file)
@@ -44,6 +44,7 @@
 #include "block.h"
 #include "observer.h"
 #include "infcall.h"
+#include "dwarf2.h"
 
 #include "spu-tdep.h"
 
@@ -1448,6 +1449,13 @@ spu_return_value (struct gdbarch *gdbarch, struct type *func_type,
                  gdb_byte *out, const gdb_byte *in)
 {
   enum return_value_convention rvc;
+  int opencl_vector = 0;
+
+  if (func_type
+      && TYPE_CALLING_CONVENTION (func_type) == DW_CC_GDB_IBM_OpenCL
+      && TYPE_CODE (type) == TYPE_CODE_ARRAY
+      && TYPE_VECTOR (type))
+    opencl_vector = 1;
 
   if (TYPE_LENGTH (type) <= (SPU_ARGN_REGNUM - SPU_ARG1_REGNUM + 1) * 16)
     rvc = RETURN_VALUE_REGISTER_CONVENTION;
@@ -1459,7 +1467,10 @@ spu_return_value (struct gdbarch *gdbarch, struct type *func_type,
       switch (rvc)
        {
        case RETURN_VALUE_REGISTER_CONVENTION:
-         spu_value_to_regcache (regcache, SPU_ARG1_REGNUM, type, in);
+         if (opencl_vector && TYPE_LENGTH (type) == 2)
+           regcache_cooked_write_part (regcache, SPU_ARG1_REGNUM, 2, 2, in);
+         else
+           spu_value_to_regcache (regcache, SPU_ARG1_REGNUM, type, in);
          break;
 
        case RETURN_VALUE_STRUCT_CONVENTION:
@@ -1472,7 +1483,10 @@ spu_return_value (struct gdbarch *gdbarch, struct type *func_type,
       switch (rvc)
        {
        case RETURN_VALUE_REGISTER_CONVENTION:
-         spu_regcache_to_value (regcache, SPU_ARG1_REGNUM, type, out);
+         if (opencl_vector && TYPE_LENGTH (type) == 2)
+           regcache_cooked_read_part (regcache, SPU_ARG1_REGNUM, 2, 2, out);
+         else
+           spu_regcache_to_value (regcache, SPU_ARG1_REGNUM, type, out);
          break;
 
        case RETURN_VALUE_STRUCT_CONVENTION:
index 3cb8d41f5ef543018b036f341d7091bca21b8484..19aec4c09e43c31a421f20719ff7d7767c05ad7b 100644 (file)
@@ -1,3 +1,9 @@
+2011-02-08  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * gdb.opencl/callfuncs.cl: New file.
+       * gdb.opencl/callfuncs.exp: New test.
+       * gdb.opencl/Makefile.in (EXECUTABLES): Add callfuncs.
+
 2011-02-08  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * gdb.arch/altivec-abi.c (vec_func): Make use of intv_on_stack_f
index c12aef3e8187c2db3be511838f5554fe05e2ef6f..7dec34c2df805fc3ec390d7476d23269357d9a07 100644 (file)
@@ -1,7 +1,7 @@
 VPATH = @srcdir@
 srcdir = @srcdir@
 
-EXECUTABLES = datatypes vec_comps convs_casts operators
+EXECUTABLES = callfuncs datatypes vec_comps convs_casts operators
 
 all info install-info dvi install uninstall installcheck check:
        @echo "Nothing to be done for $@..."
diff --git a/gdb/testsuite/gdb.opencl/callfuncs.cl b/gdb/testsuite/gdb.opencl/callfuncs.cl
new file mode 100644 (file)
index 0000000..6d53ee0
--- /dev/null
@@ -0,0 +1,218 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   Contributed by Ulrich Weigand <ulrich.weigand.ibm.com>  */
+
+__constant int opencl_version = __OPENCL_VERSION__;
+
+#ifdef HAVE_cl_khr_fp64
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+__constant int have_cl_khr_fp64 = 1;
+#else
+__constant int have_cl_khr_fp64 = 0;
+#endif
+
+#ifdef HAVE_cl_khr_fp16
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+__constant int have_cl_khr_fp16 = 1;
+#else
+__constant int have_cl_khr_fp16 = 0;
+#endif
+
+#define def_call_func(type) \
+  type call_##type (type a, type b) { return a + b; }
+
+#ifdef CL_VERSION_1_1
+#define def_call_family(type) \
+  def_call_func(type) \
+  def_call_func(type##2) \
+  def_call_func(type##3) \
+  def_call_func(type##4) \
+  def_call_func(type##8) \
+  def_call_func(type##16)
+#else
+#define def_call_family(type) \
+  def_call_func(type) \
+  def_call_func(type##2) \
+  def_call_func(type##4) \
+  def_call_func(type##8) \
+  def_call_func(type##16)
+#endif
+
+def_call_family(char)
+def_call_family(uchar)
+def_call_family(short)
+def_call_family(ushort)
+def_call_family(int)
+def_call_family(uint)
+def_call_family(long)
+def_call_family(ulong)
+#ifdef cl_khr_fp16
+def_call_family(half)
+#endif
+def_call_family(float)
+#ifdef cl_khr_fp64
+def_call_family(double)
+#endif
+
+#define call_func(type, var) \
+  var = call_##type (var, var);
+
+#ifdef CL_VERSION_1_1
+#define call_family(type, var) \
+  call_func(type, var) \
+  call_func(type##2, var##2) \
+  call_func(type##3, var##3) \
+  call_func(type##4, var##4) \
+  call_func(type##8, var##8) \
+  call_func(type##16, var##16)
+#else
+#define call_family(type, var) \
+  call_func(type, var) \
+  call_func(type##2, var##2) \
+  call_func(type##4, var##4) \
+  call_func(type##8, var##8) \
+  call_func(type##16, var##16)
+#endif
+
+__kernel void testkernel (__global int *data)
+{
+  bool b = 0;
+
+  char   c   = 1;
+  char2  c2  = (char2) (1, 2);
+#ifdef CL_VERSION_1_1
+  char3  c3  = (char3) (1, 2, 3);
+#endif
+  char4  c4  = (char4) (1, 2, 3, 4);
+  char8  c8  = (char8) (1, 2, 3, 4, 5, 6, 7, 8);
+  char16 c16 = (char16)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+
+  uchar   uc   = 1;
+  uchar2  uc2  = (uchar2) (1, 2);
+#ifdef CL_VERSION_1_1
+  uchar3  uc3  = (uchar3) (1, 2, 3);
+#endif
+  uchar4  uc4  = (uchar4) (1, 2, 3, 4);
+  uchar8  uc8  = (uchar8) (1, 2, 3, 4, 5, 6, 7, 8);
+  uchar16 uc16 = (uchar16)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+
+  short   s   = 1;
+  short2  s2  = (short2) (1, 2);
+#ifdef CL_VERSION_1_1
+  short3  s3  = (short3) (1, 2, 3);
+#endif
+  short4  s4  = (short4) (1, 2, 3, 4);
+  short8  s8  = (short8) (1, 2, 3, 4, 5, 6, 7, 8);
+  short16 s16 = (short16)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+
+  ushort   us   = 1;
+  ushort2  us2  = (ushort2) (1, 2);
+#ifdef CL_VERSION_1_1
+  ushort3  us3  = (ushort3) (1, 2, 3);
+#endif
+  ushort4  us4  = (ushort4) (1, 2, 3, 4);
+  ushort8  us8  = (ushort8) (1, 2, 3, 4, 5, 6, 7, 8);
+  ushort16 us16 = (ushort16)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+
+  int   i   = 1;
+  int2  i2  = (int2) (1, 2);
+#ifdef CL_VERSION_1_1
+  int3  i3  = (int3) (1, 2, 3);
+#endif
+  int4  i4  = (int4) (1, 2, 3, 4);
+  int8  i8  = (int8) (1, 2, 3, 4, 5, 6, 7, 8);
+  int16 i16 = (int16)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+
+  uint   ui   = 1;
+  uint2  ui2  = (uint2) (1, 2);
+#ifdef CL_VERSION_1_1
+  uint3  ui3  = (uint3) (1, 2, 3);
+#endif
+  uint4  ui4  = (uint4) (1, 2, 3, 4);
+  uint8  ui8  = (uint8) (1, 2, 3, 4, 5, 6, 7, 8);
+  uint16 ui16 = (uint16)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+
+  long   l   = 1;
+  long2  l2  = (long2) (1, 2);
+#ifdef CL_VERSION_1_1
+  long3  l3  = (long3) (1, 2, 3);
+#endif
+  long4  l4  = (long4) (1, 2, 3, 4);
+  long8  l8  = (long8) (1, 2, 3, 4, 5, 6, 7, 8);
+  long16 l16 = (long16)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+
+  ulong   ul   = 1;
+  ulong2  ul2  = (ulong2) (1, 2);
+#ifdef CL_VERSION_1_1
+  ulong3  ul3  = (ulong3) (1, 2, 3);
+#endif
+  ulong4  ul4  = (ulong4) (1, 2, 3, 4);
+  ulong8  ul8  = (ulong8) (1, 2, 3, 4, 5, 6, 7, 8);
+  ulong16 ul16 = (ulong16)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+
+#ifdef cl_khr_fp16
+  half   h   = 1.0;
+  half2  h2  = (half2) (1.0, 2.0);
+#ifdef CL_VERSION_1_1
+  half3  h3  = (half3) (1.0, 2.0, 3.0);
+#endif
+  half4  h4  = (half4) (1.0, 2.0, 3.0, 4.0);
+  half8  h8  = (half8) (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
+  half16 h16 = (half16)(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
+#endif
+
+  float   f   = 1.0;
+  float2  f2  = (float2) (1.0, 2.0);
+#ifdef CL_VERSION_1_1
+  float3  f3  = (float3) (1.0, 2.0, 3.0);
+#endif
+  float4  f4  = (float4) (1.0, 2.0, 3.0, 4.0);
+  float8  f8  = (float8) (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
+  float16 f16 = (float16)(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
+
+#ifdef cl_khr_fp64
+  double   d   = 1.0;
+  double2  d2  = (double2) (1.0, 2.0);
+#ifdef CL_VERSION_1_1
+  double3  d3  = (double3) (1.0, 2.0, 3.0);
+#endif
+  double4  d4  = (double4) (1.0, 2.0, 3.0, 4.0);
+  double8  d8  = (double8) (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
+  double16 d16 = (double16)(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
+#endif
+
+  /* marker! */
+
+  call_family (char, c);
+  call_family (uchar, uc);
+  call_family (short, s);
+  call_family (ushort, us);
+  call_family (int, i);
+  call_family (uint, ui);
+  call_family (long, l);
+  call_family (ulong, ul);
+#ifdef cl_khr_fp16
+  call_family (half, h);
+#endif
+  call_family (float, f);
+#ifdef cl_khr_fp64
+  call_family (double, d);
+#endif
+
+  data[get_global_id(0)] = 1;
+}
diff --git a/gdb/testsuite/gdb.opencl/callfuncs.exp b/gdb/testsuite/gdb.opencl/callfuncs.exp
new file mode 100644 (file)
index 0000000..f435589
--- /dev/null
@@ -0,0 +1,102 @@
+# Copyright 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+#
+# Contributed by Ulrich Weigand <ulrich.weigand@de.ibm.com>.
+#
+# Tests OpenCL function calling conventions.
+
+if $tracelevel {
+    strace $tracelevel
+}
+
+load_lib opencl.exp
+
+if { [skip_opencl_tests] } {
+    return 0
+}
+
+set testfile "callfuncs"
+set clprogram [remote_download target ${srcdir}/${subdir}/${testfile}.cl]
+
+# Compile the generic OpenCL host app
+if { [gdb_compile_opencl_hostapp "${clprogram}" "${testfile}" "" ] != "" } {
+    untested ${testfile}.exp
+    return -1
+}
+
+gdb_exit
+gdb_start
+
+# Load the OpenCL app
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${objdir}/${subdir}/${testfile}
+
+# Set breakpoint at the OpenCL kernel
+gdb_test "tbreak testkernel" \
+    "" \
+    "Set pending breakpoint" \
+    ".*Function \"testkernel\" not defined.*Make breakpoint pending.*y or \\\[n\\\]. $" \
+    "y"
+
+gdb_run_cmd
+gdb_test "" ".*reakpoint.*1.*testkernel.*" "run"
+
+# Continue to the marker
+gdb_breakpoint [gdb_get_line_number "marker" "${clprogram}"]
+gdb_continue_to_breakpoint "marker"
+
+# Check if the language was switched to opencl
+gdb_test "show language" "The current source language is \"auto; currently opencl\"\."
+
+# Prevent multi-threaded execution during inferior calls
+gdb_test_no_output "set scheduler-locking on"
+
+# Retrieve some information about the OpenCL version and the availability of extensions
+set opencl_version [get_integer_valueof "opencl_version" 0]
+set have_cl_khr_fp64 [get_integer_valueof "have_cl_khr_fp64" 0]
+set have_cl_khr_fp16 [get_integer_valueof "have_cl_khr_fp16" 0]
+
+# Check function call / return sequence
+proc call_test { type var } {
+  global opencl_version
+
+  gdb_test "print/d call_${type} (${var}, ${var})" " = 2"
+  gdb_test "print/d call_${type}2 (${var}2, ${var}2)" " = \\{2, 4\\}"
+  if { ${opencl_version} >= 110 } {
+    gdb_test "print/d call_${type}3 (${var}3, ${var}3)" " = \\{2, 4, 6\\}"
+  }
+  gdb_test "print/d call_${type}4 (${var}4, ${var}4)" " = \\{2, 4, 6, 8\\}"
+  gdb_test "print/d call_${type}8 (${var}8, ${var}8)" " = \\{2, 4, 6, 8, 10, 12, 14, 16\\}"
+  gdb_test "print/d call_${type}16 (${var}16, ${var}16)" " = \\{2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32\\}"
+}
+
+call_test "char" "c"
+call_test "uchar" "uc"
+call_test "short" "s"
+call_test "ushort" "us"
+call_test "int" "i"
+call_test "uint" "ui"
+call_test "long" "l"
+call_test "ulong" "ul"
+if { ${have_cl_khr_fp16} } {
+  call_test "half" "h"
+}
+call_test "float" "f"
+if { ${have_cl_khr_fp64} } {
+  call_test "double" "d"
+}
+
+# Delete the OpenCL program source
+remote_file target delete ${clprogram}
index c96d35855b3cfae5db6bdde73258e64d7c9776a4..2a19c6133f1d134f90f56fa81f1642b9c49defc9 100644 (file)
@@ -1,3 +1,7 @@
+2011-02-08  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * dwarf2.h (enum dwarf_calling_convention): Add DW_CC_GDB_IBM_OpenCL.
+
 2011-01-12  Iain Sandoe  <iains@gcc.gnu.org>
 
        * dwarf2.h: Update value for DW_AT_hi_user.
index ad00aac09b8a960025d8f41d5ed36c304a959587..7729ad86ddb067476895ee68a9de6183de9edd46 100644 (file)
@@ -754,7 +754,15 @@ enum dwarf_calling_convention
     DW_CC_hi_user = 0xff,
 
     DW_CC_GNU_renesas_sh = 0x40,
-    DW_CC_GNU_borland_fastcall_i386 = 0x41
+    DW_CC_GNU_borland_fastcall_i386 = 0x41,
+
+    /* This DW_CC_ value is not currently generated by any toolchain.  It is
+       used internally to GDB to indicate OpenCL C functions that have been
+       compiled with the IBM XL C for OpenCL compiler and use a non-platform
+       calling convention for passing OpenCL C vector types.  This value may
+       be changed freely as long as it does not conflict with any other DW_CC_
+       value defined here.  */
+    DW_CC_GDB_IBM_OpenCL = 0xff
   };
 
 /* Inline attribute.  */