1/* This testcase is part of GDB, the GNU debugger.
2
3   Copyright 2010-2023 Free Software Foundation, Inc.
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18   Contributed by Ken Werner <ken.werner@de.ibm.com>  */
19
20/* Utility macros and functions for OpenCL applications.  */
21
22#include "cl_util.h"
23
24#include <stdlib.h>
25#include <errno.h>
26#include <sys/stat.h>
27#include <string.h>
28
29const char *get_clerror_string (int errcode)
30{
31  switch (errcode)
32    {
33    case CL_SUCCESS:
34      return "CL_SUCCESS";
35    case CL_DEVICE_NOT_FOUND:
36      return "CL_DEVICE_NOT_FOUND";
37    case CL_DEVICE_NOT_AVAILABLE:
38      return "CL_DEVICE_NOT_AVAILABLE";
39    case CL_COMPILER_NOT_AVAILABLE:
40      return "CL_COMPILER_NOT_AVAILABLE";
41    case CL_MEM_OBJECT_ALLOCATION_FAILURE:
42      return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
43    case CL_OUT_OF_RESOURCES:
44      return "CL_OUT_OF_RESOURCES";
45    case CL_OUT_OF_HOST_MEMORY:
46      return "CL_OUT_OF_HOST_MEMORY";
47    case CL_PROFILING_INFO_NOT_AVAILABLE:
48      return "CL_PROFILING_INFO_NOT_AVAILABLE";
49    case CL_MEM_COPY_OVERLAP:
50      return "CL_MEM_COPY_OVERLAP";
51    case CL_IMAGE_FORMAT_MISMATCH:
52      return "CL_IMAGE_FORMAT_MISMATCH";
53    case CL_IMAGE_FORMAT_NOT_SUPPORTED:
54      return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
55    case CL_BUILD_PROGRAM_FAILURE:
56      return "CL_BUILD_PROGRAM_FAILURE";
57    case CL_MAP_FAILURE:
58      return "CL_MAP_FAILURE";
59    case CL_INVALID_VALUE:
60      return "CL_INVALID_VALUE";
61    case CL_INVALID_DEVICE_TYPE:
62      return "CL_INVALID_DEVICE_TYPE";
63    case CL_INVALID_PLATFORM:
64      return "CL_INVALID_PLATFORM";
65    case CL_INVALID_DEVICE:
66      return "CL_INVALID_DEVICE";
67    case CL_INVALID_CONTEXT:
68      return "CL_INVALID_CONTEXT";
69    case CL_INVALID_QUEUE_PROPERTIES:
70      return "CL_INVALID_QUEUE_PROPERTIES";
71    case CL_INVALID_COMMAND_QUEUE:
72      return "CL_INVALID_COMMAND_QUEUE";
73    case CL_INVALID_HOST_PTR:
74      return "CL_INVALID_HOST_PTR";
75    case CL_INVALID_MEM_OBJECT:
76      return "CL_INVALID_MEM_OBJECT";
77    case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
78      return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
79    case CL_INVALID_IMAGE_SIZE:
80      return "CL_INVALID_IMAGE_SIZE";
81    case CL_INVALID_SAMPLER:
82      return "CL_INVALID_SAMPLER";
83    case CL_INVALID_BINARY:
84      return "CL_INVALID_BINARY";
85    case CL_INVALID_BUILD_OPTIONS:
86      return "CL_INVALID_BUILD_OPTIONS";
87    case CL_INVALID_PROGRAM:
88      return "CL_INVALID_PROGRAM";
89    case CL_INVALID_PROGRAM_EXECUTABLE:
90      return "CL_INVALID_PROGRAM_EXECUTABLE";
91    case CL_INVALID_KERNEL_NAME:
92      return "CL_INVALID_KERNEL_NAME";
93    case CL_INVALID_KERNEL_DEFINITION:
94      return "CL_INVALID_KERNEL_DEFINITION";
95    case CL_INVALID_KERNEL:
96      return "CL_INVALID_KERNEL";
97    case CL_INVALID_ARG_INDEX:
98      return "CL_INVALID_ARG_INDEX";
99    case CL_INVALID_ARG_VALUE:
100      return "CL_INVALID_ARG_VALUE";
101    case CL_INVALID_ARG_SIZE:
102      return "CL_INVALID_ARG_SIZE";
103    case CL_INVALID_KERNEL_ARGS:
104      return "CL_INVALID_KERNEL_ARGS";
105    case CL_INVALID_WORK_DIMENSION:
106      return "CL_INVALID_WORK_DIMENSION";
107    case CL_INVALID_WORK_GROUP_SIZE:
108      return "CL_INVALID_WORK_GROUP_SIZE";
109    case CL_INVALID_WORK_ITEM_SIZE:
110      return "CL_INVALID_WORK_ITEM_SIZE";
111    case CL_INVALID_GLOBAL_OFFSET:
112      return "CL_INVALID_GLOBAL_OFFSET";
113    case CL_INVALID_EVENT_WAIT_LIST:
114      return "CL_INVALID_EVENT_WAIT_LIST";
115    case CL_INVALID_EVENT:
116      return "CL_INVALID_EVENT";
117    case CL_INVALID_OPERATION:
118      return "CL_INVALID_OPERATION";
119    case CL_INVALID_GL_OBJECT:
120      return "CL_INVALID_GL_OBJECT";
121    case CL_INVALID_BUFFER_SIZE:
122      return "CL_INVALID_BUFFER_SIZE";
123    case CL_INVALID_MIP_LEVEL:
124      return "CL_INVALID_MIP_LEVEL";
125#ifndef CL_PLATFORM_NVIDIA
126    case CL_INVALID_GLOBAL_WORK_SIZE:
127      return "CL_INVALID_GLOBAL_WORK_SIZE";
128#endif
129    default:
130      return "Unknown";
131    };
132}
133
134
135void print_clinfo ()
136{
137  char *s = NULL;
138  size_t len;
139  unsigned i, j;
140  cl_uint platform_count;
141  cl_platform_id *platforms;
142
143  /* Determine number of OpenCL Platforms available.  */
144  clGetPlatformIDs (0, NULL, &platform_count);
145  printf ("number of OpenCL Platforms available:\t%d\n", platform_count);
146  /* Get platforms.  */
147  platforms
148    = (cl_platform_id*) malloc (sizeof (cl_platform_id) * platform_count);
149  if (platforms == NULL)
150    {
151      fprintf (stderr, "malloc failed\n");
152      exit (EXIT_FAILURE);
153    }
154  clGetPlatformIDs (platform_count, platforms, NULL);
155
156  /* Querying platforms.  */
157  for (i = 0; i < platform_count; i++)
158    {
159      cl_device_id *devices;
160      cl_uint device_count;
161      cl_device_id default_dev;
162      printf (" OpenCL Platform:                       %d\n", i);
163
164#define PRINT_PF_INFO(PARM)\
165      clGetPlatformInfo (platforms[i], PARM, 0, NULL, &len); \
166      s = realloc (s, len); \
167      clGetPlatformInfo (platforms[i], PARM, len, s, NULL); \
168      printf ("  %-36s%s\n", #PARM ":", s);
169
170      PRINT_PF_INFO (CL_PLATFORM_PROFILE)
171      PRINT_PF_INFO (CL_PLATFORM_VERSION)
172      PRINT_PF_INFO (CL_PLATFORM_NAME)
173      PRINT_PF_INFO (CL_PLATFORM_VENDOR)
174      PRINT_PF_INFO (CL_PLATFORM_EXTENSIONS)
175#undef PRINT_PF_INFO
176
177      clGetDeviceIDs (platforms[i], CL_DEVICE_TYPE_DEFAULT, 1, &default_dev,
178		      NULL);
179      clGetDeviceInfo (default_dev, CL_DEVICE_NAME, 0, NULL, &len);
180      s = realloc (s, len);
181      clGetDeviceInfo (default_dev, CL_DEVICE_NAME, len, s, NULL);
182      printf ("  CL_DEVICE_TYPE_DEFAULT:             %s\n", s);
183
184      /* Determine number of devices.  */
185      clGetDeviceIDs (platforms[i], CL_DEVICE_TYPE_ALL, 0, NULL, &device_count);
186      printf ("\n  number of OpenCL Devices available:   %d\n", device_count);
187      /* Get devices.  */
188      devices = (cl_device_id*) malloc (sizeof (cl_device_id) * device_count);
189      if (devices == NULL)
190	{
191	  fprintf (stderr, "malloc failed\n");
192	  exit (EXIT_FAILURE);
193	}
194      clGetDeviceIDs (platforms[i], CL_DEVICE_TYPE_ALL, device_count, devices,
195		      NULL);
196
197      /* Querying devices.  */
198      for (j = 0; j < device_count; j++)
199	{
200	  cl_device_type dtype;
201	  cl_device_mem_cache_type mctype;
202	  cl_device_local_mem_type mtype;
203	  cl_device_fp_config fpcfg;
204	  cl_device_exec_capabilities xcap;
205	  cl_command_queue_properties qprops;
206	  cl_bool clbool;
207	  cl_uint cluint;
208	  cl_ulong clulong;
209	  size_t sizet;
210	  size_t workitem_size[3];
211	  printf ("   OpenCL Device:                       %d\n", j);
212
213#define PRINT_DEV_INFO(PARM)\
214	  clGetDeviceInfo (devices[j], PARM, 0, NULL, &len); \
215	  s = realloc (s, len); \
216	  clGetDeviceInfo (devices[j], PARM, len, s, NULL); \
217	  printf ("    %-41s%s\n", #PARM ":", s);
218
219	  PRINT_DEV_INFO (CL_DEVICE_NAME)
220	  PRINT_DEV_INFO (CL_DRIVER_VERSION)
221	  PRINT_DEV_INFO (CL_DEVICE_VENDOR)
222	  clGetDeviceInfo (devices[j], CL_DEVICE_VENDOR_ID, sizeof (cluint),
223			   &cluint, NULL);
224	  printf ("    CL_DEVICE_VENDOR_ID:                     %d\n", cluint);
225
226	  clGetDeviceInfo (devices[j], CL_DEVICE_TYPE, sizeof (dtype), &dtype, NULL);
227	  if (dtype & CL_DEVICE_TYPE_CPU)
228	    printf ("    CL_DEVICE_TYPE:                          CL_DEVICE_TYPE_CPU\n");
229	  if (dtype & CL_DEVICE_TYPE_GPU)
230	    printf ("    CL_DEVICE_TYPE:                          CL_DEVICE_TYPE_GPU\n");
231	  if (dtype & CL_DEVICE_TYPE_ACCELERATOR)
232	    printf ("    CL_DEVICE_TYPE:                          CL_DEVICE_TYPE_ACCELERATOR\n");
233	  if (dtype & CL_DEVICE_TYPE_DEFAULT)
234	    printf ("    CL_DEVICE_TYPE:                          CL_DEVICE_TYPE_DEFAULT\n");
235
236	  clGetDeviceInfo (devices[j], CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof (cluint), &cluint, NULL);
237	  printf ("    CL_DEVICE_MAX_CLOCK_FREQUENCY:           %d\n", cluint);
238
239	  PRINT_DEV_INFO (CL_DEVICE_PROFILE)
240	  PRINT_DEV_INFO (CL_DEVICE_EXTENSIONS)
241
242	  clGetDeviceInfo (devices[j], CL_DEVICE_AVAILABLE, sizeof (clbool), &clbool, NULL);
243	  if (clbool == CL_TRUE)
244	    printf ("    CL_DEVICE_AVAILABLE:                     CL_TRUE\n");
245	  else
246	    printf ("    CL_DEVICE_AVAILABLE:                     CL_FALSE\n");
247	  clGetDeviceInfo (devices[j], CL_DEVICE_ENDIAN_LITTLE, sizeof (clbool), &clbool, NULL);
248	  if (clbool == CL_TRUE)
249	    printf ("    CL_DEVICE_ENDIAN_LITTLE:                 CL_TRUE\n");
250	  else
251	    printf ("    CL_DEVICE_ENDIAN_LITTLE:                 CL_FALSE\n");
252
253	  clGetDeviceInfo (devices[j], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof (cluint), &cluint, NULL);
254	  printf ("    CL_DEVICE_MAX_COMPUTE_UNITS:             %d\n", cluint);
255	  clGetDeviceInfo (devices[j], CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof (sizet), &sizet, NULL);
256	  printf ("    CL_DEVICE_MAX_WORK_GROUP_SIZE:           %d\n", sizet);
257	  clGetDeviceInfo (devices[j], CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof (cluint), &cluint, NULL);
258	  printf ("    CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:      %d\n", cluint);
259	  clGetDeviceInfo (devices[j], CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof (workitem_size), &workitem_size, NULL);
260	  printf ("    CL_DEVICE_MAX_WORK_ITEM_SIZES:           %d / %d / %d\n", workitem_size[0], workitem_size[1], workitem_size[2]);
261
262	  clGetDeviceInfo (devices[j], CL_DEVICE_ADDRESS_BITS, sizeof (cluint), &cluint, NULL);
263	  printf ("    CL_DEVICE_ADDRESS_BITS:                  %d\n", cluint);
264
265	  clGetDeviceInfo (devices[j], CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof (clulong), &clulong, NULL);
266	  printf ("    CL_DEVICE_MAX_MEM_ALLOC_SIZE:            %llu\n", clulong);
267	  clGetDeviceInfo (devices[j], CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof (cluint), &cluint, NULL);
268	  printf ("    CL_DEVICE_MEM_BASE_ADDR_ALIGN:           %d\n", cluint);
269	  clGetDeviceInfo(devices[j], CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, sizeof (cluint), &cluint, NULL);
270	  printf ("    CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE:      %d\n", cluint);
271	  clGetDeviceInfo(devices[j], CL_DEVICE_MAX_PARAMETER_SIZE, sizeof (sizet), &sizet, NULL);
272	  printf ("    CL_DEVICE_MAX_PARAMETER_SIZE:            %d\n", sizet);
273	  clGetDeviceInfo(devices[j], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof (clulong), &clulong, NULL);
274	  printf ("    CL_DEVICE_GLOBAL_MEM_SIZE:               %llu\n", clulong);
275
276	  clGetDeviceInfo (devices[j], CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, sizeof (mctype), &mctype, NULL);
277	  if (mctype & CL_NONE)
278	    printf ("    CL_DEVICE_GLOBAL_MEM_CACHE_TYPE:         CL_NONE\n");
279	  if (mctype & CL_READ_ONLY_CACHE)
280	    printf ("    CL_DEVICE_GLOBAL_MEM_CACHE_TYPE:         CL_READ_ONLY_CACHE\n");
281	  if (mctype & CL_READ_WRITE_CACHE)
282	    printf ("    CL_DEVICE_GLOBAL_MEM_CACHE_TYPE:         CL_READ_WRITE_CACHE\n");
283
284	  clGetDeviceInfo (devices[j], CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, sizeof (clulong), &clulong, NULL);
285	  printf ("    CL_DEVICE_GLOBAL_MEM_CACHE_SIZE:         %llu\n", clulong);
286	  clGetDeviceInfo (devices[j], CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, sizeof (cluint), &cluint, NULL);
287	  printf ("    CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE:     %d\n", cluint);
288
289	  clGetDeviceInfo (devices[j], CL_DEVICE_LOCAL_MEM_TYPE, sizeof (mtype), &mtype, NULL);
290	  if (mtype & CL_LOCAL)
291	    printf ("    CL_DEVICE_LOCAL_MEM_TYPE:                CL_LOCAL\n");
292	  if (mtype & CL_GLOBAL)
293	    printf ("    CL_DEVICE_LOCAL_MEM_TYPE:                CL_GLOBAL\n");
294
295	  clGetDeviceInfo (devices[j], CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, sizeof (cluint), &cluint, NULL);
296	  printf ("    CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE:      %d\n", cluint);
297	  clGetDeviceInfo (devices[j], CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof (cluint), &cluint, NULL);
298	  printf ("    CL_DEVICE_MEM_BASE_ADDR_ALIGN:           %d\n", cluint);
299	  clGetDeviceInfo (devices[j], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof (cluint), &cluint, NULL);
300	  printf ("    CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR:   %d\n", cluint);
301	  clGetDeviceInfo (devices[j], CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, sizeof (cluint), &cluint, NULL);
302	  printf ("    CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT:  %d\n", cluint);
303	  clGetDeviceInfo (devices[j], CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, sizeof (cluint), &cluint, NULL);
304	  printf ("    CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT:    %d\n", cluint);
305	  clGetDeviceInfo (devices[j], CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, sizeof (cluint), &cluint, NULL);
306	  printf ("    CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG:   %d\n", cluint);
307	  clGetDeviceInfo (devices[j], CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, sizeof (cluint), &cluint, NULL);
308	  printf ("    CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT:  %d\n", cluint);
309	  clGetDeviceInfo (devices[j], CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, sizeof (cluint), &cluint, NULL);
310	  printf ("    CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: %d\n", cluint);
311
312	  clGetDeviceInfo (devices[j], CL_DEVICE_SINGLE_FP_CONFIG, sizeof (fpcfg), &fpcfg, NULL);
313	  if (fpcfg & CL_FP_DENORM)
314	    printf ("    CL_DEVICE_SINGLE_FP_CONFIG:              CL_FP_DENORM\n");
315	  if (fpcfg & CL_FP_INF_NAN)
316	    printf ("    CL_DEVICE_SINGLE_FP_CONFIG:              CL_FP_INF_NAN\n");
317	  if (fpcfg & CL_FP_ROUND_TO_NEAREST)
318	    printf ("    CL_DEVICE_SINGLE_FP_CONFIG:              CL_FP_ROUND_TO_NEAREST\n");
319	  if (fpcfg & CL_FP_ROUND_TO_ZERO)
320	    printf ("    CL_DEVICE_SINGLE_FP_CONFIG:              CL_FP_ROUND_TO_ZERO\n");
321
322	  clGetDeviceInfo (devices[j], CL_DEVICE_EXECUTION_CAPABILITIES, sizeof (xcap), &xcap, NULL);
323	  if (xcap & CL_EXEC_KERNEL )
324	    printf ("    CL_DEVICE_EXECUTION_CAPABILITIES:        CL_EXEC_KERNEL\n");
325	  if (xcap & CL_EXEC_NATIVE_KERNEL)
326	    printf ("    CL_DEVICE_EXECUTION_CAPABILITIES:        CL_EXEC_NATIVE_KERNEL\n");
327
328	  clGetDeviceInfo (devices[j], CL_DEVICE_QUEUE_PROPERTIES, sizeof (qprops), &qprops, NULL);
329	  if (qprops & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE)
330	    printf ("    CL_DEVICE_QUEUE_PROPERTIES:              CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE\n");
331	  if (qprops & CL_QUEUE_PROFILING_ENABLE)
332	    printf ("    CL_DEVICE_QUEUE_PROPERTIES:              CL_QUEUE_PROFILING_ENABLE\n");
333
334	  clGetDeviceInfo (devices[j], CL_DEVICE_PROFILING_TIMER_RESOLUTION, sizeof (sizet), &sizet, NULL);
335	  printf ("    CL_DEVICE_PROFILING_TIMER_RESOLUTION:    %d\n", sizet);
336
337	  clGetDeviceInfo (devices[j], CL_DEVICE_COMPILER_AVAILABLE, sizeof (clbool), &clbool, NULL);
338	  if (clbool == CL_TRUE)
339	    printf ("    CL_DEVICE_COMPILER_AVAILABLE:            CL_TRUE\n");
340	  else
341	    printf ("    CL_DEVICE_COMPILER_AVAILABLE:            CL_FALSE\n");
342	  clGetDeviceInfo (devices[j], CL_DEVICE_ERROR_CORRECTION_SUPPORT, sizeof (clbool), &clbool, NULL);
343	  if (clbool == CL_TRUE)
344	    printf ("    CL_DEVICE_ERROR_CORRECTION_SUPPORT:      CL_TRUE\n");
345	  else
346	    printf ("    CL_DEVICE_ERROR_CORRECTION_SUPPORT:      CL_FALSE\n");
347
348	  clGetDeviceInfo (devices[j], CL_DEVICE_IMAGE_SUPPORT, sizeof (clbool), &clbool, NULL);
349	  if (clbool == CL_FALSE)
350	    {
351	      printf ("    CL_DEVICE_IMAGE_SUPPORT:                 CL_FALSE\n");
352	    }
353	  else
354	    {
355	      printf ("    CL_DEVICE_IMAGE_SUPPORT:                 CL_TRUE\n");
356	      clGetDeviceInfo (devices[j], CL_DEVICE_MAX_SAMPLERS, sizeof (cluint), &cluint, NULL);
357	      printf ("    CL_DEVICE_MAX_SAMPLERS:                  %d\n", cluint);
358	      clGetDeviceInfo (devices[j], CL_DEVICE_MAX_READ_IMAGE_ARGS, sizeof (cluint), &cluint, NULL);
359	      printf ("    CL_DEVICE_MAX_READ_IMAGE_ARGS:           %d\n", cluint);
360	      clGetDeviceInfo (devices[j], CL_DEVICE_MAX_WRITE_IMAGE_ARGS, sizeof (cluint), &cluint, NULL);
361	      printf ("    CL_DEVICE_MAX_WRITE_IMAGE_ARGS:          %d\n", cluint);
362	      clGetDeviceInfo (devices[j], CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof (sizet), &sizet, NULL);
363	      printf ("    CL_DEVICE_IMAGE2D_MAX_WIDTH:             %d\n", sizet);
364	      clGetDeviceInfo (devices[j], CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof (sizet), &sizet, NULL);
365	      printf ("    CL_DEVICE_IMAGE2D_MAX_HEIGHT:            %d\n", sizet);
366	      clGetDeviceInfo (devices[j], CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof (sizet), &sizet, NULL);
367	      printf ("    CL_DEVICE_IMAGE3D_MAX_WIDTH:             %d\n", sizet);
368	      clGetDeviceInfo (devices[j], CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof (sizet), &sizet, NULL);
369	      printf ("    CL_DEVICE_IMAGE3D_MAX_HEIGHT:            %d\n", sizet);
370	      clGetDeviceInfo (devices[j], CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof (sizet), &sizet, NULL);
371	      printf ("    CL_DEVICE_IMAGE3D_MAX_DEPTH:             %d\n", sizet);
372	    }
373#undef PRINT_DEV_INFO
374	} /* devices */
375      free (devices);
376    } /* platforms */
377  free (s);
378  free (platforms);
379}
380
381
382const char *
383read_file (const char * const filename, size_t *size)
384{
385  char *buf = NULL;
386  FILE *fd;
387  struct stat st;
388  if (stat (filename, &st) == -1)
389    {
390      /* Check if the file exists.  */
391      if (errno == ENOENT)
392	return buf;
393      perror ("stat failed");
394      exit (EXIT_FAILURE);
395    }
396  buf = (char *) malloc (st.st_size);
397  if (buf == NULL)
398    {
399      fprintf (stderr, "malloc failed\n");
400      exit (EXIT_FAILURE);
401    }
402  fd = fopen (filename, "r");
403  if (fd == NULL)
404    {
405      perror ("fopen failed");
406      free (buf);
407      exit (EXIT_FAILURE);
408    }
409  if (fread (buf, st.st_size, 1, fd) != 1)
410    {
411      fprintf (stderr, "fread failed\n");
412      free (buf);
413      fclose (fd);
414      exit (EXIT_FAILURE);
415    }
416  fclose (fd);
417  *size = st.st_size;
418  return buf;
419}
420
421
422void
423save_program_binaries (cl_program program)
424{
425  cl_device_id *devices;
426  cl_uint device_count;
427  size_t *sizes;
428  unsigned char **binaries;
429  unsigned i, j;
430
431  /* Query the amount of devices for the given program.  */
432  CHK (clGetProgramInfo (program, CL_PROGRAM_NUM_DEVICES, sizeof (cl_uint),
433			&device_count, NULL));
434
435  /* Get the sizes of the binaries.  */
436  sizes = (size_t*) malloc (sizeof (size_t) * device_count);
437  if (sizes == NULL)
438    {
439      fprintf (stderr, "malloc failed\n");
440      exit (EXIT_FAILURE);
441    }
442  CHK (clGetProgramInfo (program, CL_PROGRAM_BINARY_SIZES, sizeof (sizes),
443			 sizes, NULL));
444
445  /* Get the binaries.  */
446  binaries
447    = (unsigned char **) malloc (sizeof (unsigned char *) * device_count);
448  if (binaries == NULL)
449    {
450      fprintf (stderr, "malloc failed\n");
451      exit (EXIT_FAILURE);
452    }
453  for (i = 0; i < device_count; i++)
454    {
455      binaries[i] = (unsigned char *) malloc (sizes[i]);
456      if (binaries[i] == NULL)
457	{
458	  fprintf (stderr, "malloc failed\n");
459	  exit (EXIT_FAILURE);
460	}
461    }
462  CHK (clGetProgramInfo (program, CL_PROGRAM_BINARIES, sizeof (binaries),
463			 binaries, NULL));
464
465  /* Get the devices for the given program to extract the file names.  */
466  devices = (cl_device_id*) malloc (sizeof (cl_device_id) * device_count);
467  if (devices == NULL)
468    {
469      fprintf (stderr, "malloc failed\n");
470      exit (EXIT_FAILURE);
471    }
472  CHK (clGetProgramInfo (program, CL_PROGRAM_DEVICES, sizeof (devices),
473			 devices, NULL));
474
475  for (i = 0; i < device_count; i++)
476    {
477      FILE *fd;
478      char *dev_name = NULL;
479      size_t len;
480      CHK (clGetDeviceInfo (devices[i], CL_DEVICE_NAME, 0, NULL, &len));
481      dev_name = malloc (len);
482      if (dev_name == NULL)
483	{
484	  fprintf (stderr, "malloc failed\n");
485	  exit (EXIT_FAILURE);
486	}
487      CHK (clGetDeviceInfo (devices[i], CL_DEVICE_NAME, len, dev_name, NULL));
488      /* Convert spaces to underscores.  */
489      for (j = 0; j < strlen (dev_name); j++)
490	{
491	  if (dev_name[j] == ' ')
492	    dev_name[j] = '_';
493	}
494
495      /*  Save the binaries.  */
496      printf ("saving program binary for device: %s\n", dev_name);
497      /* Save binaries[i].  */
498      fd = fopen (dev_name, "w");
499      if (fd == NULL)
500	{
501	  perror ("fopen failed");
502	  exit (EXIT_FAILURE);
503	}
504      if (fwrite (binaries[i], sizes[i], 1, fd) != 1)
505	{
506	  fprintf (stderr, "fwrite failed\n");
507	  for (j = i; j < device_count; j++)
508	    free (binaries[j]);
509	  fclose (fd);
510	  exit (EXIT_FAILURE);
511	}
512      fclose (fd);
513      free (binaries[i]);
514      free (dev_name);
515      free (sizes);
516    }
517  free (devices);
518  free (binaries);
519}
520