xref: /aosp_15_r20/external/OpenCL-CTS/test_common/harness/testHarness.cpp (revision 6467f958c7de8070b317fc65bcb0f6472e388d82)
1*6467f958SSadaf Ebrahimi //
2*6467f958SSadaf Ebrahimi // Copyright (c) 2017-2019 The Khronos Group Inc.
3*6467f958SSadaf Ebrahimi //
4*6467f958SSadaf Ebrahimi // Licensed under the Apache License, Version 2.0 (the "License");
5*6467f958SSadaf Ebrahimi // you may not use this file except in compliance with the License.
6*6467f958SSadaf Ebrahimi // You may obtain a copy of the License at
7*6467f958SSadaf Ebrahimi //
8*6467f958SSadaf Ebrahimi //    http://www.apache.org/licenses/LICENSE-2.0
9*6467f958SSadaf Ebrahimi //
10*6467f958SSadaf Ebrahimi // Unless required by applicable law or agreed to in writing, software
11*6467f958SSadaf Ebrahimi // distributed under the License is distributed on an "AS IS" BASIS,
12*6467f958SSadaf Ebrahimi // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6467f958SSadaf Ebrahimi // See the License for the specific language governing permissions and
14*6467f958SSadaf Ebrahimi // limitations under the License.
15*6467f958SSadaf Ebrahimi //
16*6467f958SSadaf Ebrahimi #include "testHarness.h"
17*6467f958SSadaf Ebrahimi #include "compat.h"
18*6467f958SSadaf Ebrahimi #include <algorithm>
19*6467f958SSadaf Ebrahimi #include <stdio.h>
20*6467f958SSadaf Ebrahimi #include <stdlib.h>
21*6467f958SSadaf Ebrahimi #include <string.h>
22*6467f958SSadaf Ebrahimi #include <cassert>
23*6467f958SSadaf Ebrahimi #include <deque>
24*6467f958SSadaf Ebrahimi #include <mutex>
25*6467f958SSadaf Ebrahimi #include <stdexcept>
26*6467f958SSadaf Ebrahimi #include <thread>
27*6467f958SSadaf Ebrahimi #include <vector>
28*6467f958SSadaf Ebrahimi #include "errorHelpers.h"
29*6467f958SSadaf Ebrahimi #include "kernelHelpers.h"
30*6467f958SSadaf Ebrahimi #include "fpcontrol.h"
31*6467f958SSadaf Ebrahimi #include "typeWrappers.h"
32*6467f958SSadaf Ebrahimi #include "imageHelpers.h"
33*6467f958SSadaf Ebrahimi #include "parseParameters.h"
34*6467f958SSadaf Ebrahimi 
35*6467f958SSadaf Ebrahimi #if !defined(_WIN32)
36*6467f958SSadaf Ebrahimi #include <sys/utsname.h>
37*6467f958SSadaf Ebrahimi #include <unistd.h>
38*6467f958SSadaf Ebrahimi #endif
39*6467f958SSadaf Ebrahimi 
40*6467f958SSadaf Ebrahimi #if defined(__APPLE__)
41*6467f958SSadaf Ebrahimi #include <sys/sysctl.h>
42*6467f958SSadaf Ebrahimi #endif
43*6467f958SSadaf Ebrahimi 
44*6467f958SSadaf Ebrahimi #include <time.h>
45*6467f958SSadaf Ebrahimi 
46*6467f958SSadaf Ebrahimi #if !defined(__APPLE__)
47*6467f958SSadaf Ebrahimi #include <CL/cl.h>
48*6467f958SSadaf Ebrahimi #endif
49*6467f958SSadaf Ebrahimi 
50*6467f958SSadaf Ebrahimi int gTestsPassed = 0;
51*6467f958SSadaf Ebrahimi int gTestsFailed = 0;
52*6467f958SSadaf Ebrahimi int gFailCount;
53*6467f958SSadaf Ebrahimi int gTestCount;
54*6467f958SSadaf Ebrahimi cl_uint gRandomSeed = 0;
55*6467f958SSadaf Ebrahimi cl_uint gReSeed = 0;
56*6467f958SSadaf Ebrahimi 
57*6467f958SSadaf Ebrahimi int gFlushDenormsToZero = 0;
58*6467f958SSadaf Ebrahimi int gInfNanSupport = 1;
59*6467f958SSadaf Ebrahimi int gIsEmbedded = 0;
60*6467f958SSadaf Ebrahimi int gHasLong = 1;
61*6467f958SSadaf Ebrahimi bool gCoreILProgram = true;
62*6467f958SSadaf Ebrahimi 
63*6467f958SSadaf Ebrahimi #define DEFAULT_NUM_ELEMENTS 0x4000
64*6467f958SSadaf Ebrahimi 
saveResultsToJson(const char * suiteName,test_definition testList[],unsigned char selectedTestList[],test_status resultTestList[],int testNum)65*6467f958SSadaf Ebrahimi static int saveResultsToJson(const char *suiteName, test_definition testList[],
66*6467f958SSadaf Ebrahimi                              unsigned char selectedTestList[],
67*6467f958SSadaf Ebrahimi                              test_status resultTestList[], int testNum)
68*6467f958SSadaf Ebrahimi {
69*6467f958SSadaf Ebrahimi     char *fileName = getenv("CL_CONFORMANCE_RESULTS_FILENAME");
70*6467f958SSadaf Ebrahimi     if (fileName == nullptr)
71*6467f958SSadaf Ebrahimi     {
72*6467f958SSadaf Ebrahimi         return EXIT_SUCCESS;
73*6467f958SSadaf Ebrahimi     }
74*6467f958SSadaf Ebrahimi 
75*6467f958SSadaf Ebrahimi     FILE *file = fopen(fileName, "w");
76*6467f958SSadaf Ebrahimi     if (NULL == file)
77*6467f958SSadaf Ebrahimi     {
78*6467f958SSadaf Ebrahimi         log_error("ERROR: Failed to open '%s' for writing results.\n",
79*6467f958SSadaf Ebrahimi                   fileName);
80*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
81*6467f958SSadaf Ebrahimi     }
82*6467f958SSadaf Ebrahimi 
83*6467f958SSadaf Ebrahimi     const char *save_map[] = { "success", "failure" };
84*6467f958SSadaf Ebrahimi     const char *result_map[] = { "pass", "fail", "skip" };
85*6467f958SSadaf Ebrahimi     const char *linebreak[] = { "", ",\n" };
86*6467f958SSadaf Ebrahimi     int add_linebreak = 0;
87*6467f958SSadaf Ebrahimi 
88*6467f958SSadaf Ebrahimi     fprintf(file, "{\n");
89*6467f958SSadaf Ebrahimi     fprintf(file, "\t\"cmd\": \"%s\",\n", suiteName);
90*6467f958SSadaf Ebrahimi     fprintf(file, "\t\"results\": {\n");
91*6467f958SSadaf Ebrahimi 
92*6467f958SSadaf Ebrahimi     for (int i = 0; i < testNum; ++i)
93*6467f958SSadaf Ebrahimi     {
94*6467f958SSadaf Ebrahimi         if (selectedTestList[i])
95*6467f958SSadaf Ebrahimi         {
96*6467f958SSadaf Ebrahimi             fprintf(file, "%s\t\t\"%s\": \"%s\"", linebreak[add_linebreak],
97*6467f958SSadaf Ebrahimi                     testList[i].name, result_map[(int)resultTestList[i]]);
98*6467f958SSadaf Ebrahimi             add_linebreak = 1;
99*6467f958SSadaf Ebrahimi         }
100*6467f958SSadaf Ebrahimi     }
101*6467f958SSadaf Ebrahimi     fprintf(file, "\n");
102*6467f958SSadaf Ebrahimi 
103*6467f958SSadaf Ebrahimi     fprintf(file, "\t}\n");
104*6467f958SSadaf Ebrahimi     fprintf(file, "}\n");
105*6467f958SSadaf Ebrahimi 
106*6467f958SSadaf Ebrahimi     int ret = fclose(file) ? EXIT_FAILURE : EXIT_SUCCESS;
107*6467f958SSadaf Ebrahimi 
108*6467f958SSadaf Ebrahimi     log_info("Saving results to %s: %s!\n", fileName, save_map[ret]);
109*6467f958SSadaf Ebrahimi 
110*6467f958SSadaf Ebrahimi     return ret;
111*6467f958SSadaf Ebrahimi }
112*6467f958SSadaf Ebrahimi 
runTestHarness(int argc,const char * argv[],int testNum,test_definition testList[],int forceNoContextCreation,cl_command_queue_properties queueProps)113*6467f958SSadaf Ebrahimi int runTestHarness(int argc, const char *argv[], int testNum,
114*6467f958SSadaf Ebrahimi                    test_definition testList[], int forceNoContextCreation,
115*6467f958SSadaf Ebrahimi                    cl_command_queue_properties queueProps)
116*6467f958SSadaf Ebrahimi {
117*6467f958SSadaf Ebrahimi     return runTestHarnessWithCheck(argc, argv, testNum, testList,
118*6467f958SSadaf Ebrahimi                                    forceNoContextCreation, queueProps, NULL);
119*6467f958SSadaf Ebrahimi }
120*6467f958SSadaf Ebrahimi 
suite_did_not_pass_init(const char * suiteName,test_status status,int testNum,test_definition testList[])121*6467f958SSadaf Ebrahimi int suite_did_not_pass_init(const char *suiteName, test_status status,
122*6467f958SSadaf Ebrahimi                             int testNum, test_definition testList[])
123*6467f958SSadaf Ebrahimi {
124*6467f958SSadaf Ebrahimi     std::vector<unsigned char> selectedTestList(testNum, 1);
125*6467f958SSadaf Ebrahimi     std::vector<test_status> resultTestList(testNum, status);
126*6467f958SSadaf Ebrahimi 
127*6467f958SSadaf Ebrahimi     int ret = saveResultsToJson(suiteName, testList, selectedTestList.data(),
128*6467f958SSadaf Ebrahimi                                 resultTestList.data(), testNum);
129*6467f958SSadaf Ebrahimi 
130*6467f958SSadaf Ebrahimi     log_info("Test %s while initialization\n",
131*6467f958SSadaf Ebrahimi              status == TEST_SKIP ? "skipped" : "failed");
132*6467f958SSadaf Ebrahimi     log_info("%s %d of %d tests.\n", status == TEST_SKIP ? "SKIPPED" : "FAILED",
133*6467f958SSadaf Ebrahimi              testNum, testNum);
134*6467f958SSadaf Ebrahimi 
135*6467f958SSadaf Ebrahimi     if (ret != EXIT_SUCCESS)
136*6467f958SSadaf Ebrahimi     {
137*6467f958SSadaf Ebrahimi         return ret;
138*6467f958SSadaf Ebrahimi     }
139*6467f958SSadaf Ebrahimi 
140*6467f958SSadaf Ebrahimi     return status == TEST_SKIP ? EXIT_SUCCESS : EXIT_FAILURE;
141*6467f958SSadaf Ebrahimi }
142*6467f958SSadaf Ebrahimi 
version_expected_info(const char * test_name,const char * api_name,const char * expected_version,const char * device_version)143*6467f958SSadaf Ebrahimi void version_expected_info(const char *test_name, const char *api_name,
144*6467f958SSadaf Ebrahimi                            const char *expected_version,
145*6467f958SSadaf Ebrahimi                            const char *device_version)
146*6467f958SSadaf Ebrahimi {
147*6467f958SSadaf Ebrahimi     log_info("%s skipped (requires at least %s version %s, but the device "
148*6467f958SSadaf Ebrahimi              "reports %s version %s)\n",
149*6467f958SSadaf Ebrahimi              test_name, api_name, expected_version, api_name, device_version);
150*6467f958SSadaf Ebrahimi }
runTestHarnessWithCheck(int argc,const char * argv[],int testNum,test_definition testList[],int forceNoContextCreation,cl_command_queue_properties queueProps,DeviceCheckFn deviceCheckFn)151*6467f958SSadaf Ebrahimi int runTestHarnessWithCheck(int argc, const char *argv[], int testNum,
152*6467f958SSadaf Ebrahimi                             test_definition testList[],
153*6467f958SSadaf Ebrahimi                             int forceNoContextCreation,
154*6467f958SSadaf Ebrahimi                             cl_command_queue_properties queueProps,
155*6467f958SSadaf Ebrahimi                             DeviceCheckFn deviceCheckFn)
156*6467f958SSadaf Ebrahimi {
157*6467f958SSadaf Ebrahimi     test_start();
158*6467f958SSadaf Ebrahimi 
159*6467f958SSadaf Ebrahimi     cl_device_type device_type = CL_DEVICE_TYPE_DEFAULT;
160*6467f958SSadaf Ebrahimi     cl_uint num_platforms = 0;
161*6467f958SSadaf Ebrahimi     cl_platform_id *platforms;
162*6467f958SSadaf Ebrahimi     cl_device_id device;
163*6467f958SSadaf Ebrahimi     int num_elements = DEFAULT_NUM_ELEMENTS;
164*6467f958SSadaf Ebrahimi     cl_uint num_devices = 0;
165*6467f958SSadaf Ebrahimi     cl_device_id *devices = NULL;
166*6467f958SSadaf Ebrahimi     cl_uint choosen_device_index = 0;
167*6467f958SSadaf Ebrahimi     cl_uint choosen_platform_index = 0;
168*6467f958SSadaf Ebrahimi 
169*6467f958SSadaf Ebrahimi     int err, ret;
170*6467f958SSadaf Ebrahimi     char *endPtr;
171*6467f958SSadaf Ebrahimi     int based_on_env_var = 0;
172*6467f958SSadaf Ebrahimi 
173*6467f958SSadaf Ebrahimi 
174*6467f958SSadaf Ebrahimi     /* Check for environment variable to set device type */
175*6467f958SSadaf Ebrahimi     char *env_mode = getenv("CL_DEVICE_TYPE");
176*6467f958SSadaf Ebrahimi     if (env_mode != NULL)
177*6467f958SSadaf Ebrahimi     {
178*6467f958SSadaf Ebrahimi         based_on_env_var = 1;
179*6467f958SSadaf Ebrahimi         if (strcmp(env_mode, "gpu") == 0
180*6467f958SSadaf Ebrahimi             || strcmp(env_mode, "CL_DEVICE_TYPE_GPU") == 0)
181*6467f958SSadaf Ebrahimi             device_type = CL_DEVICE_TYPE_GPU;
182*6467f958SSadaf Ebrahimi         else if (strcmp(env_mode, "cpu") == 0
183*6467f958SSadaf Ebrahimi                  || strcmp(env_mode, "CL_DEVICE_TYPE_CPU") == 0)
184*6467f958SSadaf Ebrahimi             device_type = CL_DEVICE_TYPE_CPU;
185*6467f958SSadaf Ebrahimi         else if (strcmp(env_mode, "accelerator") == 0
186*6467f958SSadaf Ebrahimi                  || strcmp(env_mode, "CL_DEVICE_TYPE_ACCELERATOR") == 0)
187*6467f958SSadaf Ebrahimi             device_type = CL_DEVICE_TYPE_ACCELERATOR;
188*6467f958SSadaf Ebrahimi         else if (strcmp(env_mode, "default") == 0
189*6467f958SSadaf Ebrahimi                  || strcmp(env_mode, "CL_DEVICE_TYPE_DEFAULT") == 0)
190*6467f958SSadaf Ebrahimi             device_type = CL_DEVICE_TYPE_DEFAULT;
191*6467f958SSadaf Ebrahimi         else
192*6467f958SSadaf Ebrahimi         {
193*6467f958SSadaf Ebrahimi             log_error("Unknown CL_DEVICE_TYPE env variable setting: "
194*6467f958SSadaf Ebrahimi                       "%s.\nAborting...\n",
195*6467f958SSadaf Ebrahimi                       env_mode);
196*6467f958SSadaf Ebrahimi             abort();
197*6467f958SSadaf Ebrahimi         }
198*6467f958SSadaf Ebrahimi     }
199*6467f958SSadaf Ebrahimi 
200*6467f958SSadaf Ebrahimi #if defined(__APPLE__)
201*6467f958SSadaf Ebrahimi     {
202*6467f958SSadaf Ebrahimi         // report on any unusual library search path indirection
203*6467f958SSadaf Ebrahimi         char *libSearchPath = getenv("DYLD_LIBRARY_PATH");
204*6467f958SSadaf Ebrahimi         if (libSearchPath)
205*6467f958SSadaf Ebrahimi             log_info("*** DYLD_LIBRARY_PATH = \"%s\"\n", libSearchPath);
206*6467f958SSadaf Ebrahimi 
207*6467f958SSadaf Ebrahimi         // report on any unusual framework search path indirection
208*6467f958SSadaf Ebrahimi         char *frameworkSearchPath = getenv("DYLD_FRAMEWORK_PATH");
209*6467f958SSadaf Ebrahimi         if (libSearchPath)
210*6467f958SSadaf Ebrahimi             log_info("*** DYLD_FRAMEWORK_PATH = \"%s\"\n", frameworkSearchPath);
211*6467f958SSadaf Ebrahimi     }
212*6467f958SSadaf Ebrahimi #endif
213*6467f958SSadaf Ebrahimi 
214*6467f958SSadaf Ebrahimi     env_mode = getenv("CL_DEVICE_INDEX");
215*6467f958SSadaf Ebrahimi     if (env_mode != NULL)
216*6467f958SSadaf Ebrahimi     {
217*6467f958SSadaf Ebrahimi         choosen_device_index = atoi(env_mode);
218*6467f958SSadaf Ebrahimi     }
219*6467f958SSadaf Ebrahimi 
220*6467f958SSadaf Ebrahimi     env_mode = getenv("CL_PLATFORM_INDEX");
221*6467f958SSadaf Ebrahimi     if (env_mode != NULL)
222*6467f958SSadaf Ebrahimi     {
223*6467f958SSadaf Ebrahimi         choosen_platform_index = atoi(env_mode);
224*6467f958SSadaf Ebrahimi     }
225*6467f958SSadaf Ebrahimi 
226*6467f958SSadaf Ebrahimi     /* Process the command line arguments */
227*6467f958SSadaf Ebrahimi 
228*6467f958SSadaf Ebrahimi     argc = parseCustomParam(argc, argv);
229*6467f958SSadaf Ebrahimi     if (argc == -1)
230*6467f958SSadaf Ebrahimi     {
231*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
232*6467f958SSadaf Ebrahimi     }
233*6467f958SSadaf Ebrahimi 
234*6467f958SSadaf Ebrahimi     /* Special case: just list the tests */
235*6467f958SSadaf Ebrahimi     if ((argc > 1)
236*6467f958SSadaf Ebrahimi         && (!strcmp(argv[1], "-list") || !strcmp(argv[1], "-h")
237*6467f958SSadaf Ebrahimi             || !strcmp(argv[1], "--help")))
238*6467f958SSadaf Ebrahimi     {
239*6467f958SSadaf Ebrahimi         char *fileName = getenv("CL_CONFORMANCE_RESULTS_FILENAME");
240*6467f958SSadaf Ebrahimi 
241*6467f958SSadaf Ebrahimi         log_info(
242*6467f958SSadaf Ebrahimi             "Usage: %s [<test name>*] [pid<num>] [id<num>] [<device type>]\n",
243*6467f958SSadaf Ebrahimi             argv[0]);
244*6467f958SSadaf Ebrahimi         log_info("\t<test name>\tOne or more of: (wildcard character '*') "
245*6467f958SSadaf Ebrahimi                  "(default *)\n");
246*6467f958SSadaf Ebrahimi         log_info("\tpid<num>\tIndicates platform at index <num> should be used "
247*6467f958SSadaf Ebrahimi                  "(default 0).\n");
248*6467f958SSadaf Ebrahimi         log_info("\tid<num>\t\tIndicates device at index <num> should be used "
249*6467f958SSadaf Ebrahimi                  "(default 0).\n");
250*6467f958SSadaf Ebrahimi         log_info("\t<device_type>\tcpu|gpu|accelerator|<CL_DEVICE_TYPE_*> "
251*6467f958SSadaf Ebrahimi                  "(default CL_DEVICE_TYPE_DEFAULT)\n");
252*6467f958SSadaf Ebrahimi         log_info("\n");
253*6467f958SSadaf Ebrahimi         log_info("\tNOTE: You may pass environment variable "
254*6467f958SSadaf Ebrahimi                  "CL_CONFORMANCE_RESULTS_FILENAME (currently '%s')\n",
255*6467f958SSadaf Ebrahimi                  fileName != NULL ? fileName : "<undefined>");
256*6467f958SSadaf Ebrahimi         log_info("\t      to save results to JSON file.\n");
257*6467f958SSadaf Ebrahimi 
258*6467f958SSadaf Ebrahimi         log_info("\n");
259*6467f958SSadaf Ebrahimi         log_info("Test names:\n");
260*6467f958SSadaf Ebrahimi         for (int i = 0; i < testNum; i++)
261*6467f958SSadaf Ebrahimi         {
262*6467f958SSadaf Ebrahimi             log_info("\t%s\n", testList[i].name);
263*6467f958SSadaf Ebrahimi         }
264*6467f958SSadaf Ebrahimi         return EXIT_SUCCESS;
265*6467f958SSadaf Ebrahimi     }
266*6467f958SSadaf Ebrahimi 
267*6467f958SSadaf Ebrahimi     /* How are we supposed to seed the random # generators? */
268*6467f958SSadaf Ebrahimi     if (argc > 1 && strcmp(argv[argc - 1], "randomize") == 0)
269*6467f958SSadaf Ebrahimi     {
270*6467f958SSadaf Ebrahimi         gRandomSeed = (cl_uint)time(NULL);
271*6467f958SSadaf Ebrahimi         log_info("Random seed: %u.\n", gRandomSeed);
272*6467f958SSadaf Ebrahimi         gReSeed = 1;
273*6467f958SSadaf Ebrahimi         argc--;
274*6467f958SSadaf Ebrahimi     }
275*6467f958SSadaf Ebrahimi     else
276*6467f958SSadaf Ebrahimi     {
277*6467f958SSadaf Ebrahimi         log_info(" Initializing random seed to 0.\n");
278*6467f958SSadaf Ebrahimi     }
279*6467f958SSadaf Ebrahimi 
280*6467f958SSadaf Ebrahimi     /* Do we have an integer to specify the number of elements to pass to tests?
281*6467f958SSadaf Ebrahimi      */
282*6467f958SSadaf Ebrahimi     if (argc > 1)
283*6467f958SSadaf Ebrahimi     {
284*6467f958SSadaf Ebrahimi         ret = (int)strtol(argv[argc - 1], &endPtr, 10);
285*6467f958SSadaf Ebrahimi         if (endPtr != argv[argc - 1] && *endPtr == 0)
286*6467f958SSadaf Ebrahimi         {
287*6467f958SSadaf Ebrahimi             /* By spec, this means the entire string was a valid integer, so we
288*6467f958SSadaf Ebrahimi              * treat it as a num_elements spec */
289*6467f958SSadaf Ebrahimi             /* (hence why we stored the result in ret first) */
290*6467f958SSadaf Ebrahimi             num_elements = ret;
291*6467f958SSadaf Ebrahimi             log_info("Testing with num_elements of %d\n", num_elements);
292*6467f958SSadaf Ebrahimi             argc--;
293*6467f958SSadaf Ebrahimi         }
294*6467f958SSadaf Ebrahimi     }
295*6467f958SSadaf Ebrahimi 
296*6467f958SSadaf Ebrahimi     /* Do we have a CPU/GPU specification? */
297*6467f958SSadaf Ebrahimi     if (argc > 1)
298*6467f958SSadaf Ebrahimi     {
299*6467f958SSadaf Ebrahimi         if (strcmp(argv[argc - 1], "gpu") == 0
300*6467f958SSadaf Ebrahimi             || strcmp(argv[argc - 1], "CL_DEVICE_TYPE_GPU") == 0)
301*6467f958SSadaf Ebrahimi         {
302*6467f958SSadaf Ebrahimi             device_type = CL_DEVICE_TYPE_GPU;
303*6467f958SSadaf Ebrahimi             argc--;
304*6467f958SSadaf Ebrahimi         }
305*6467f958SSadaf Ebrahimi         else if (strcmp(argv[argc - 1], "cpu") == 0
306*6467f958SSadaf Ebrahimi                  || strcmp(argv[argc - 1], "CL_DEVICE_TYPE_CPU") == 0)
307*6467f958SSadaf Ebrahimi         {
308*6467f958SSadaf Ebrahimi             device_type = CL_DEVICE_TYPE_CPU;
309*6467f958SSadaf Ebrahimi             argc--;
310*6467f958SSadaf Ebrahimi         }
311*6467f958SSadaf Ebrahimi         else if (strcmp(argv[argc - 1], "accelerator") == 0
312*6467f958SSadaf Ebrahimi                  || strcmp(argv[argc - 1], "CL_DEVICE_TYPE_ACCELERATOR") == 0)
313*6467f958SSadaf Ebrahimi         {
314*6467f958SSadaf Ebrahimi             device_type = CL_DEVICE_TYPE_ACCELERATOR;
315*6467f958SSadaf Ebrahimi             argc--;
316*6467f958SSadaf Ebrahimi         }
317*6467f958SSadaf Ebrahimi         else if (strcmp(argv[argc - 1], "CL_DEVICE_TYPE_DEFAULT") == 0)
318*6467f958SSadaf Ebrahimi         {
319*6467f958SSadaf Ebrahimi             device_type = CL_DEVICE_TYPE_DEFAULT;
320*6467f958SSadaf Ebrahimi             argc--;
321*6467f958SSadaf Ebrahimi         }
322*6467f958SSadaf Ebrahimi     }
323*6467f958SSadaf Ebrahimi 
324*6467f958SSadaf Ebrahimi     /* Did we choose a specific device index? */
325*6467f958SSadaf Ebrahimi     if (argc > 1)
326*6467f958SSadaf Ebrahimi     {
327*6467f958SSadaf Ebrahimi         if (strlen(argv[argc - 1]) >= 3 && argv[argc - 1][0] == 'i'
328*6467f958SSadaf Ebrahimi             && argv[argc - 1][1] == 'd')
329*6467f958SSadaf Ebrahimi         {
330*6467f958SSadaf Ebrahimi             choosen_device_index = atoi(&(argv[argc - 1][2]));
331*6467f958SSadaf Ebrahimi             argc--;
332*6467f958SSadaf Ebrahimi         }
333*6467f958SSadaf Ebrahimi     }
334*6467f958SSadaf Ebrahimi 
335*6467f958SSadaf Ebrahimi     /* Did we choose a specific platform index? */
336*6467f958SSadaf Ebrahimi     if (argc > 1)
337*6467f958SSadaf Ebrahimi     {
338*6467f958SSadaf Ebrahimi         if (strlen(argv[argc - 1]) >= 3 && argv[argc - 1][0] == 'p'
339*6467f958SSadaf Ebrahimi             && argv[argc - 1][1] == 'i' && argv[argc - 1][2] == 'd')
340*6467f958SSadaf Ebrahimi         {
341*6467f958SSadaf Ebrahimi             choosen_platform_index = atoi(&(argv[argc - 1][3]));
342*6467f958SSadaf Ebrahimi             argc--;
343*6467f958SSadaf Ebrahimi         }
344*6467f958SSadaf Ebrahimi     }
345*6467f958SSadaf Ebrahimi 
346*6467f958SSadaf Ebrahimi 
347*6467f958SSadaf Ebrahimi     switch (device_type)
348*6467f958SSadaf Ebrahimi     {
349*6467f958SSadaf Ebrahimi         case CL_DEVICE_TYPE_GPU: log_info("Requesting GPU device "); break;
350*6467f958SSadaf Ebrahimi         case CL_DEVICE_TYPE_CPU: log_info("Requesting CPU device "); break;
351*6467f958SSadaf Ebrahimi         case CL_DEVICE_TYPE_ACCELERATOR:
352*6467f958SSadaf Ebrahimi             log_info("Requesting Accelerator device ");
353*6467f958SSadaf Ebrahimi             break;
354*6467f958SSadaf Ebrahimi         case CL_DEVICE_TYPE_DEFAULT:
355*6467f958SSadaf Ebrahimi             log_info("Requesting Default device ");
356*6467f958SSadaf Ebrahimi             break;
357*6467f958SSadaf Ebrahimi         default: log_error("Requesting unknown device "); return EXIT_FAILURE;
358*6467f958SSadaf Ebrahimi     }
359*6467f958SSadaf Ebrahimi     log_info(based_on_env_var ? "based on environment variable "
360*6467f958SSadaf Ebrahimi                               : "based on command line ");
361*6467f958SSadaf Ebrahimi     log_info("for platform index %d and device index %d\n",
362*6467f958SSadaf Ebrahimi              choosen_platform_index, choosen_device_index);
363*6467f958SSadaf Ebrahimi 
364*6467f958SSadaf Ebrahimi #if defined(__APPLE__)
365*6467f958SSadaf Ebrahimi #if defined(__i386__) || defined(__x86_64__)
366*6467f958SSadaf Ebrahimi #define kHasSSE3 0x00000008
367*6467f958SSadaf Ebrahimi #define kHasSupplementalSSE3 0x00000100
368*6467f958SSadaf Ebrahimi #define kHasSSE4_1 0x00000400
369*6467f958SSadaf Ebrahimi #define kHasSSE4_2 0x00000800
370*6467f958SSadaf Ebrahimi     /* check our environment for a hint to disable SSE variants */
371*6467f958SSadaf Ebrahimi     {
372*6467f958SSadaf Ebrahimi         const char *env = getenv("CL_MAX_SSE");
373*6467f958SSadaf Ebrahimi         if (env)
374*6467f958SSadaf Ebrahimi         {
375*6467f958SSadaf Ebrahimi             extern int _cpu_capabilities;
376*6467f958SSadaf Ebrahimi             int mask = 0;
377*6467f958SSadaf Ebrahimi             if (0 == strcasecmp(env, "SSE4.1"))
378*6467f958SSadaf Ebrahimi                 mask = kHasSSE4_2;
379*6467f958SSadaf Ebrahimi             else if (0 == strcasecmp(env, "SSSE3"))
380*6467f958SSadaf Ebrahimi                 mask = kHasSSE4_2 | kHasSSE4_1;
381*6467f958SSadaf Ebrahimi             else if (0 == strcasecmp(env, "SSE3"))
382*6467f958SSadaf Ebrahimi                 mask = kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3;
383*6467f958SSadaf Ebrahimi             else if (0 == strcasecmp(env, "SSE2"))
384*6467f958SSadaf Ebrahimi                 mask =
385*6467f958SSadaf Ebrahimi                     kHasSSE4_2 | kHasSSE4_1 | kHasSupplementalSSE3 | kHasSSE3;
386*6467f958SSadaf Ebrahimi             else
387*6467f958SSadaf Ebrahimi             {
388*6467f958SSadaf Ebrahimi                 log_error("Error: Unknown CL_MAX_SSE setting: %s\n", env);
389*6467f958SSadaf Ebrahimi                 return EXIT_FAILURE;
390*6467f958SSadaf Ebrahimi             }
391*6467f958SSadaf Ebrahimi 
392*6467f958SSadaf Ebrahimi             log_info("*** Environment: CL_MAX_SSE = %s ***\n", env);
393*6467f958SSadaf Ebrahimi             _cpu_capabilities &= ~mask;
394*6467f958SSadaf Ebrahimi         }
395*6467f958SSadaf Ebrahimi     }
396*6467f958SSadaf Ebrahimi #endif
397*6467f958SSadaf Ebrahimi #endif
398*6467f958SSadaf Ebrahimi 
399*6467f958SSadaf Ebrahimi     /* Get the platform */
400*6467f958SSadaf Ebrahimi     err = clGetPlatformIDs(0, NULL, &num_platforms);
401*6467f958SSadaf Ebrahimi     if (err)
402*6467f958SSadaf Ebrahimi     {
403*6467f958SSadaf Ebrahimi         print_error(err, "clGetPlatformIDs failed");
404*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
405*6467f958SSadaf Ebrahimi     }
406*6467f958SSadaf Ebrahimi 
407*6467f958SSadaf Ebrahimi     platforms =
408*6467f958SSadaf Ebrahimi         (cl_platform_id *)malloc(num_platforms * sizeof(cl_platform_id));
409*6467f958SSadaf Ebrahimi     if (!platforms || choosen_platform_index >= num_platforms)
410*6467f958SSadaf Ebrahimi     {
411*6467f958SSadaf Ebrahimi         log_error("platform index out of range -- choosen_platform_index (%d) "
412*6467f958SSadaf Ebrahimi                   ">= num_platforms (%d)\n",
413*6467f958SSadaf Ebrahimi                   choosen_platform_index, num_platforms);
414*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
415*6467f958SSadaf Ebrahimi     }
416*6467f958SSadaf Ebrahimi     BufferOwningPtr<cl_platform_id> platformsBuf(platforms);
417*6467f958SSadaf Ebrahimi 
418*6467f958SSadaf Ebrahimi     err = clGetPlatformIDs(num_platforms, platforms, NULL);
419*6467f958SSadaf Ebrahimi     if (err)
420*6467f958SSadaf Ebrahimi     {
421*6467f958SSadaf Ebrahimi         print_error(err, "clGetPlatformIDs failed");
422*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
423*6467f958SSadaf Ebrahimi     }
424*6467f958SSadaf Ebrahimi 
425*6467f958SSadaf Ebrahimi     /* Get the number of requested devices */
426*6467f958SSadaf Ebrahimi     err = clGetDeviceIDs(platforms[choosen_platform_index], device_type, 0,
427*6467f958SSadaf Ebrahimi                          NULL, &num_devices);
428*6467f958SSadaf Ebrahimi     if (err)
429*6467f958SSadaf Ebrahimi     {
430*6467f958SSadaf Ebrahimi         print_error(err, "clGetDeviceIDs failed");
431*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
432*6467f958SSadaf Ebrahimi     }
433*6467f958SSadaf Ebrahimi 
434*6467f958SSadaf Ebrahimi     devices = (cl_device_id *)malloc(num_devices * sizeof(cl_device_id));
435*6467f958SSadaf Ebrahimi     if (!devices || choosen_device_index >= num_devices)
436*6467f958SSadaf Ebrahimi     {
437*6467f958SSadaf Ebrahimi         log_error("device index out of range -- choosen_device_index (%d) >= "
438*6467f958SSadaf Ebrahimi                   "num_devices (%d)\n",
439*6467f958SSadaf Ebrahimi                   choosen_device_index, num_devices);
440*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
441*6467f958SSadaf Ebrahimi     }
442*6467f958SSadaf Ebrahimi     BufferOwningPtr<cl_device_id> devicesBuf(devices);
443*6467f958SSadaf Ebrahimi 
444*6467f958SSadaf Ebrahimi 
445*6467f958SSadaf Ebrahimi     /* Get the requested device */
446*6467f958SSadaf Ebrahimi     err = clGetDeviceIDs(platforms[choosen_platform_index], device_type,
447*6467f958SSadaf Ebrahimi                          num_devices, devices, NULL);
448*6467f958SSadaf Ebrahimi     if (err)
449*6467f958SSadaf Ebrahimi     {
450*6467f958SSadaf Ebrahimi         print_error(err, "clGetDeviceIDs failed");
451*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
452*6467f958SSadaf Ebrahimi     }
453*6467f958SSadaf Ebrahimi 
454*6467f958SSadaf Ebrahimi     device = devices[choosen_device_index];
455*6467f958SSadaf Ebrahimi 
456*6467f958SSadaf Ebrahimi     err = clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(gDeviceType),
457*6467f958SSadaf Ebrahimi                           &gDeviceType, NULL);
458*6467f958SSadaf Ebrahimi     if (err)
459*6467f958SSadaf Ebrahimi     {
460*6467f958SSadaf Ebrahimi         print_error(err, "Unable to get device type");
461*6467f958SSadaf Ebrahimi         return TEST_FAIL;
462*6467f958SSadaf Ebrahimi     }
463*6467f958SSadaf Ebrahimi 
464*6467f958SSadaf Ebrahimi     if (printDeviceHeader(device) != CL_SUCCESS)
465*6467f958SSadaf Ebrahimi     {
466*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
467*6467f958SSadaf Ebrahimi     }
468*6467f958SSadaf Ebrahimi 
469*6467f958SSadaf Ebrahimi     cl_device_fp_config fpconfig = 0;
470*6467f958SSadaf Ebrahimi     err = clGetDeviceInfo(device, CL_DEVICE_SINGLE_FP_CONFIG, sizeof(fpconfig),
471*6467f958SSadaf Ebrahimi                           &fpconfig, NULL);
472*6467f958SSadaf Ebrahimi     if (err)
473*6467f958SSadaf Ebrahimi     {
474*6467f958SSadaf Ebrahimi         print_error(err,
475*6467f958SSadaf Ebrahimi                     "clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed");
476*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
477*6467f958SSadaf Ebrahimi     }
478*6467f958SSadaf Ebrahimi 
479*6467f958SSadaf Ebrahimi     gFlushDenormsToZero = (0 == (fpconfig & CL_FP_DENORM));
480*6467f958SSadaf Ebrahimi     log_info("Supports single precision denormals: %s\n",
481*6467f958SSadaf Ebrahimi              gFlushDenormsToZero ? "NO" : "YES");
482*6467f958SSadaf Ebrahimi     log_info("sizeof( void*) = %d  (host)\n", (int)sizeof(void *));
483*6467f958SSadaf Ebrahimi 
484*6467f958SSadaf Ebrahimi     // detect whether profile of the device is embedded
485*6467f958SSadaf Ebrahimi     char profile[1024] = "";
486*6467f958SSadaf Ebrahimi     err = clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(profile), profile,
487*6467f958SSadaf Ebrahimi                           NULL);
488*6467f958SSadaf Ebrahimi     if (err)
489*6467f958SSadaf Ebrahimi     {
490*6467f958SSadaf Ebrahimi         print_error(err, "clGetDeviceInfo for CL_DEVICE_PROFILE failed\n");
491*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
492*6467f958SSadaf Ebrahimi     }
493*6467f958SSadaf Ebrahimi     gIsEmbedded = NULL != strstr(profile, "EMBEDDED_PROFILE");
494*6467f958SSadaf Ebrahimi 
495*6467f958SSadaf Ebrahimi     // detect the floating point capabilities
496*6467f958SSadaf Ebrahimi     cl_device_fp_config floatCapabilities = 0;
497*6467f958SSadaf Ebrahimi     err = clGetDeviceInfo(device, CL_DEVICE_SINGLE_FP_CONFIG,
498*6467f958SSadaf Ebrahimi                           sizeof(floatCapabilities), &floatCapabilities, NULL);
499*6467f958SSadaf Ebrahimi     if (err)
500*6467f958SSadaf Ebrahimi     {
501*6467f958SSadaf Ebrahimi         print_error(err,
502*6467f958SSadaf Ebrahimi                     "clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed\n");
503*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
504*6467f958SSadaf Ebrahimi     }
505*6467f958SSadaf Ebrahimi 
506*6467f958SSadaf Ebrahimi     // Check for problems that only embedded will have
507*6467f958SSadaf Ebrahimi     if (gIsEmbedded)
508*6467f958SSadaf Ebrahimi     {
509*6467f958SSadaf Ebrahimi         // If the device is embedded, we need to detect if the device supports
510*6467f958SSadaf Ebrahimi         // Infinity and NaN
511*6467f958SSadaf Ebrahimi         if ((floatCapabilities & CL_FP_INF_NAN) == 0) gInfNanSupport = 0;
512*6467f958SSadaf Ebrahimi 
513*6467f958SSadaf Ebrahimi         // check the extensions list to see if ulong and long are supported
514*6467f958SSadaf Ebrahimi         if (!is_extension_available(device, "cles_khr_int64")) gHasLong = 0;
515*6467f958SSadaf Ebrahimi     }
516*6467f958SSadaf Ebrahimi 
517*6467f958SSadaf Ebrahimi     cl_uint device_address_bits = 0;
518*6467f958SSadaf Ebrahimi     if ((err = clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS,
519*6467f958SSadaf Ebrahimi                                sizeof(device_address_bits),
520*6467f958SSadaf Ebrahimi                                &device_address_bits, NULL)))
521*6467f958SSadaf Ebrahimi     {
522*6467f958SSadaf Ebrahimi         print_error(err, "Unable to obtain device address bits");
523*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
524*6467f958SSadaf Ebrahimi     }
525*6467f958SSadaf Ebrahimi     if (device_address_bits)
526*6467f958SSadaf Ebrahimi         log_info("sizeof( void*) = %d  (device)\n", device_address_bits / 8);
527*6467f958SSadaf Ebrahimi     else
528*6467f958SSadaf Ebrahimi     {
529*6467f958SSadaf Ebrahimi         log_error("Invalid device address bit size returned by device.\n");
530*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
531*6467f958SSadaf Ebrahimi     }
532*6467f958SSadaf Ebrahimi     const char *suiteName = argv[0];
533*6467f958SSadaf Ebrahimi     if (gCompilationMode == kSpir_v)
534*6467f958SSadaf Ebrahimi     {
535*6467f958SSadaf Ebrahimi         test_status spirv_readiness = check_spirv_compilation_readiness(device);
536*6467f958SSadaf Ebrahimi         if (spirv_readiness != TEST_PASS)
537*6467f958SSadaf Ebrahimi         {
538*6467f958SSadaf Ebrahimi             switch (spirv_readiness)
539*6467f958SSadaf Ebrahimi             {
540*6467f958SSadaf Ebrahimi                 case TEST_PASS: break;
541*6467f958SSadaf Ebrahimi                 case TEST_FAIL:
542*6467f958SSadaf Ebrahimi                     return suite_did_not_pass_init(suiteName, TEST_FAIL,
543*6467f958SSadaf Ebrahimi                                                    testNum, testList);
544*6467f958SSadaf Ebrahimi                 case TEST_SKIP:
545*6467f958SSadaf Ebrahimi                     return suite_did_not_pass_init(suiteName, TEST_SKIP,
546*6467f958SSadaf Ebrahimi                                                    testNum, testList);
547*6467f958SSadaf Ebrahimi                 case TEST_SKIPPED_ITSELF:
548*6467f958SSadaf Ebrahimi                     return suite_did_not_pass_init(suiteName, TEST_SKIP,
549*6467f958SSadaf Ebrahimi                                                    testNum, testList);
550*6467f958SSadaf Ebrahimi             }
551*6467f958SSadaf Ebrahimi         }
552*6467f958SSadaf Ebrahimi     }
553*6467f958SSadaf Ebrahimi 
554*6467f958SSadaf Ebrahimi     /* If we have a device checking function, run it */
555*6467f958SSadaf Ebrahimi     if ((deviceCheckFn != NULL))
556*6467f958SSadaf Ebrahimi     {
557*6467f958SSadaf Ebrahimi         test_status status = deviceCheckFn(device);
558*6467f958SSadaf Ebrahimi         switch (status)
559*6467f958SSadaf Ebrahimi         {
560*6467f958SSadaf Ebrahimi             case TEST_PASS: break;
561*6467f958SSadaf Ebrahimi             case TEST_FAIL:
562*6467f958SSadaf Ebrahimi                 return suite_did_not_pass_init(suiteName, TEST_FAIL, testNum,
563*6467f958SSadaf Ebrahimi                                                testList);
564*6467f958SSadaf Ebrahimi             case TEST_SKIP:
565*6467f958SSadaf Ebrahimi                 return suite_did_not_pass_init(suiteName, TEST_SKIP, testNum,
566*6467f958SSadaf Ebrahimi                                                testList);
567*6467f958SSadaf Ebrahimi             case TEST_SKIPPED_ITSELF:
568*6467f958SSadaf Ebrahimi                 return suite_did_not_pass_init(suiteName, TEST_SKIP, testNum,
569*6467f958SSadaf Ebrahimi                                                testList);
570*6467f958SSadaf Ebrahimi         }
571*6467f958SSadaf Ebrahimi     }
572*6467f958SSadaf Ebrahimi 
573*6467f958SSadaf Ebrahimi     if (num_elements <= 0) num_elements = DEFAULT_NUM_ELEMENTS;
574*6467f958SSadaf Ebrahimi 
575*6467f958SSadaf Ebrahimi         // On most platforms which support denorm, default is FTZ off. However,
576*6467f958SSadaf Ebrahimi         // on some hardware where the reference is computed, default might be
577*6467f958SSadaf Ebrahimi         // flush denorms to zero e.g. arm. This creates issues in result
578*6467f958SSadaf Ebrahimi         // verification. Since spec allows the implementation to either flush or
579*6467f958SSadaf Ebrahimi         // not flush denorms to zero, an implementation may choose not be flush
580*6467f958SSadaf Ebrahimi         // i.e. return denorm result whereas reference result may be zero
581*6467f958SSadaf Ebrahimi         // (flushed denorm). Hence we need to disable denorm flushing on host
582*6467f958SSadaf Ebrahimi         // side where reference is being computed to make sure we get
583*6467f958SSadaf Ebrahimi         // non-flushed reference result. If implementation returns flushed
584*6467f958SSadaf Ebrahimi         // result, we correctly take care of that in verification code.
585*6467f958SSadaf Ebrahimi #if defined(__APPLE__) && defined(__arm__)
586*6467f958SSadaf Ebrahimi     FPU_mode_type oldMode;
587*6467f958SSadaf Ebrahimi     DisableFTZ(&oldMode);
588*6467f958SSadaf Ebrahimi #endif
589*6467f958SSadaf Ebrahimi     extern unsigned gNumWorkerThreads;
590*6467f958SSadaf Ebrahimi     test_harness_config config = { forceNoContextCreation, num_elements,
591*6467f958SSadaf Ebrahimi                                    queueProps, gNumWorkerThreads };
592*6467f958SSadaf Ebrahimi 
593*6467f958SSadaf Ebrahimi     int error = parseAndCallCommandLineTests(argc, argv, device, testNum,
594*6467f958SSadaf Ebrahimi                                              testList, config);
595*6467f958SSadaf Ebrahimi 
596*6467f958SSadaf Ebrahimi #if defined(__APPLE__) && defined(__arm__)
597*6467f958SSadaf Ebrahimi     // Restore the old FP mode before leaving.
598*6467f958SSadaf Ebrahimi     RestoreFPState(&oldMode);
599*6467f958SSadaf Ebrahimi #endif
600*6467f958SSadaf Ebrahimi 
601*6467f958SSadaf Ebrahimi     return (error == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
602*6467f958SSadaf Ebrahimi }
603*6467f958SSadaf Ebrahimi 
find_matching_tests(test_definition testList[],unsigned char selectedTestList[],int testNum,const char * argument,bool isWildcard)604*6467f958SSadaf Ebrahimi static int find_matching_tests(test_definition testList[],
605*6467f958SSadaf Ebrahimi                                unsigned char selectedTestList[], int testNum,
606*6467f958SSadaf Ebrahimi                                const char *argument, bool isWildcard)
607*6467f958SSadaf Ebrahimi {
608*6467f958SSadaf Ebrahimi     int found_tests = 0;
609*6467f958SSadaf Ebrahimi     size_t wildcard_length = strlen(argument) - 1; /* -1 for the asterisk */
610*6467f958SSadaf Ebrahimi 
611*6467f958SSadaf Ebrahimi     for (int i = 0; i < testNum; i++)
612*6467f958SSadaf Ebrahimi     {
613*6467f958SSadaf Ebrahimi         if ((!isWildcard && strcmp(testList[i].name, argument) == 0)
614*6467f958SSadaf Ebrahimi             || (isWildcard
615*6467f958SSadaf Ebrahimi                 && strncmp(testList[i].name, argument, wildcard_length) == 0))
616*6467f958SSadaf Ebrahimi         {
617*6467f958SSadaf Ebrahimi             if (selectedTestList[i])
618*6467f958SSadaf Ebrahimi             {
619*6467f958SSadaf Ebrahimi                 log_error("ERROR: Test '%s' has already been selected.\n",
620*6467f958SSadaf Ebrahimi                           testList[i].name);
621*6467f958SSadaf Ebrahimi                 return EXIT_FAILURE;
622*6467f958SSadaf Ebrahimi             }
623*6467f958SSadaf Ebrahimi             else if (testList[i].func == NULL)
624*6467f958SSadaf Ebrahimi             {
625*6467f958SSadaf Ebrahimi                 log_error("ERROR: Test '%s' is missing implementation.\n",
626*6467f958SSadaf Ebrahimi                           testList[i].name);
627*6467f958SSadaf Ebrahimi                 return EXIT_FAILURE;
628*6467f958SSadaf Ebrahimi             }
629*6467f958SSadaf Ebrahimi             else
630*6467f958SSadaf Ebrahimi             {
631*6467f958SSadaf Ebrahimi                 selectedTestList[i] = 1;
632*6467f958SSadaf Ebrahimi                 found_tests = 1;
633*6467f958SSadaf Ebrahimi                 if (!isWildcard)
634*6467f958SSadaf Ebrahimi                 {
635*6467f958SSadaf Ebrahimi                     break;
636*6467f958SSadaf Ebrahimi                 }
637*6467f958SSadaf Ebrahimi             }
638*6467f958SSadaf Ebrahimi         }
639*6467f958SSadaf Ebrahimi     }
640*6467f958SSadaf Ebrahimi 
641*6467f958SSadaf Ebrahimi     if (!found_tests)
642*6467f958SSadaf Ebrahimi     {
643*6467f958SSadaf Ebrahimi         log_error("ERROR: The argument '%s' did not match any test names.\n",
644*6467f958SSadaf Ebrahimi                   argument);
645*6467f958SSadaf Ebrahimi         return EXIT_FAILURE;
646*6467f958SSadaf Ebrahimi     }
647*6467f958SSadaf Ebrahimi 
648*6467f958SSadaf Ebrahimi     return EXIT_SUCCESS;
649*6467f958SSadaf Ebrahimi }
650*6467f958SSadaf Ebrahimi 
print_results(int failed,int count,const char * name)651*6467f958SSadaf Ebrahimi static void print_results(int failed, int count, const char *name)
652*6467f958SSadaf Ebrahimi {
653*6467f958SSadaf Ebrahimi     if (count < failed)
654*6467f958SSadaf Ebrahimi     {
655*6467f958SSadaf Ebrahimi         count = failed;
656*6467f958SSadaf Ebrahimi     }
657*6467f958SSadaf Ebrahimi 
658*6467f958SSadaf Ebrahimi     if (failed == 0)
659*6467f958SSadaf Ebrahimi     {
660*6467f958SSadaf Ebrahimi         if (count > 1)
661*6467f958SSadaf Ebrahimi         {
662*6467f958SSadaf Ebrahimi             log_info("PASSED %d of %d %ss.\n", count, count, name);
663*6467f958SSadaf Ebrahimi         }
664*6467f958SSadaf Ebrahimi         else
665*6467f958SSadaf Ebrahimi         {
666*6467f958SSadaf Ebrahimi             log_info("PASSED %s.\n", name);
667*6467f958SSadaf Ebrahimi         }
668*6467f958SSadaf Ebrahimi     }
669*6467f958SSadaf Ebrahimi     else if (failed > 0)
670*6467f958SSadaf Ebrahimi     {
671*6467f958SSadaf Ebrahimi         if (count > 1)
672*6467f958SSadaf Ebrahimi         {
673*6467f958SSadaf Ebrahimi             log_error("FAILED %d of %d %ss.\n", failed, count, name);
674*6467f958SSadaf Ebrahimi         }
675*6467f958SSadaf Ebrahimi         else
676*6467f958SSadaf Ebrahimi         {
677*6467f958SSadaf Ebrahimi             log_error("FAILED %s.\n", name);
678*6467f958SSadaf Ebrahimi         }
679*6467f958SSadaf Ebrahimi     }
680*6467f958SSadaf Ebrahimi }
681*6467f958SSadaf Ebrahimi 
parseAndCallCommandLineTests(int argc,const char * argv[],cl_device_id device,int testNum,test_definition testList[],const test_harness_config & config)682*6467f958SSadaf Ebrahimi int parseAndCallCommandLineTests(int argc, const char *argv[],
683*6467f958SSadaf Ebrahimi                                  cl_device_id device, int testNum,
684*6467f958SSadaf Ebrahimi                                  test_definition testList[],
685*6467f958SSadaf Ebrahimi                                  const test_harness_config &config)
686*6467f958SSadaf Ebrahimi {
687*6467f958SSadaf Ebrahimi     int ret = EXIT_SUCCESS;
688*6467f958SSadaf Ebrahimi 
689*6467f958SSadaf Ebrahimi     unsigned char *selectedTestList = (unsigned char *)calloc(testNum, 1);
690*6467f958SSadaf Ebrahimi 
691*6467f958SSadaf Ebrahimi     if (argc == 1)
692*6467f958SSadaf Ebrahimi     {
693*6467f958SSadaf Ebrahimi         /* No actual arguments, all tests will be run. */
694*6467f958SSadaf Ebrahimi         memset(selectedTestList, 1, testNum);
695*6467f958SSadaf Ebrahimi     }
696*6467f958SSadaf Ebrahimi     else
697*6467f958SSadaf Ebrahimi     {
698*6467f958SSadaf Ebrahimi         for (int i = 1; i < argc; i++)
699*6467f958SSadaf Ebrahimi         {
700*6467f958SSadaf Ebrahimi             if (strchr(argv[i], '*') != NULL)
701*6467f958SSadaf Ebrahimi             {
702*6467f958SSadaf Ebrahimi                 ret = find_matching_tests(testList, selectedTestList, testNum,
703*6467f958SSadaf Ebrahimi                                           argv[i], true);
704*6467f958SSadaf Ebrahimi             }
705*6467f958SSadaf Ebrahimi             else
706*6467f958SSadaf Ebrahimi             {
707*6467f958SSadaf Ebrahimi                 if (strcmp(argv[i], "all") == 0)
708*6467f958SSadaf Ebrahimi                 {
709*6467f958SSadaf Ebrahimi                     memset(selectedTestList, 1, testNum);
710*6467f958SSadaf Ebrahimi                     break;
711*6467f958SSadaf Ebrahimi                 }
712*6467f958SSadaf Ebrahimi                 else
713*6467f958SSadaf Ebrahimi                 {
714*6467f958SSadaf Ebrahimi                     ret = find_matching_tests(testList, selectedTestList,
715*6467f958SSadaf Ebrahimi                                               testNum, argv[i], false);
716*6467f958SSadaf Ebrahimi                 }
717*6467f958SSadaf Ebrahimi             }
718*6467f958SSadaf Ebrahimi 
719*6467f958SSadaf Ebrahimi             if (ret == EXIT_FAILURE)
720*6467f958SSadaf Ebrahimi             {
721*6467f958SSadaf Ebrahimi                 break;
722*6467f958SSadaf Ebrahimi             }
723*6467f958SSadaf Ebrahimi         }
724*6467f958SSadaf Ebrahimi     }
725*6467f958SSadaf Ebrahimi 
726*6467f958SSadaf Ebrahimi     if (ret == EXIT_SUCCESS)
727*6467f958SSadaf Ebrahimi     {
728*6467f958SSadaf Ebrahimi         std::vector<test_status> resultTestList(testNum, TEST_PASS);
729*6467f958SSadaf Ebrahimi 
730*6467f958SSadaf Ebrahimi         callTestFunctions(testList, selectedTestList, resultTestList.data(),
731*6467f958SSadaf Ebrahimi                           testNum, device, config);
732*6467f958SSadaf Ebrahimi 
733*6467f958SSadaf Ebrahimi         print_results(gFailCount, gTestCount, "sub-test");
734*6467f958SSadaf Ebrahimi         print_results(gTestsFailed, gTestsFailed + gTestsPassed, "test");
735*6467f958SSadaf Ebrahimi 
736*6467f958SSadaf Ebrahimi         ret = saveResultsToJson(argv[0], testList, selectedTestList,
737*6467f958SSadaf Ebrahimi                                 resultTestList.data(), testNum);
738*6467f958SSadaf Ebrahimi 
739*6467f958SSadaf Ebrahimi         if (std::any_of(resultTestList.begin(), resultTestList.end(),
740*6467f958SSadaf Ebrahimi                         [](test_status result) {
741*6467f958SSadaf Ebrahimi                             switch (result)
742*6467f958SSadaf Ebrahimi                             {
743*6467f958SSadaf Ebrahimi                                 case TEST_PASS:
744*6467f958SSadaf Ebrahimi                                 case TEST_SKIP: return false;
745*6467f958SSadaf Ebrahimi                                 case TEST_FAIL:
746*6467f958SSadaf Ebrahimi                                 default: return true;
747*6467f958SSadaf Ebrahimi                             };
748*6467f958SSadaf Ebrahimi                         }))
749*6467f958SSadaf Ebrahimi         {
750*6467f958SSadaf Ebrahimi             ret = EXIT_FAILURE;
751*6467f958SSadaf Ebrahimi         }
752*6467f958SSadaf Ebrahimi     }
753*6467f958SSadaf Ebrahimi 
754*6467f958SSadaf Ebrahimi     free(selectedTestList);
755*6467f958SSadaf Ebrahimi 
756*6467f958SSadaf Ebrahimi     return ret;
757*6467f958SSadaf Ebrahimi }
758*6467f958SSadaf Ebrahimi 
759*6467f958SSadaf Ebrahimi struct test_harness_state
760*6467f958SSadaf Ebrahimi {
761*6467f958SSadaf Ebrahimi     test_definition *tests;
762*6467f958SSadaf Ebrahimi     test_status *results;
763*6467f958SSadaf Ebrahimi     cl_device_id device;
764*6467f958SSadaf Ebrahimi     test_harness_config config;
765*6467f958SSadaf Ebrahimi };
766*6467f958SSadaf Ebrahimi 
767*6467f958SSadaf Ebrahimi static std::deque<int> gTestQueue;
768*6467f958SSadaf Ebrahimi static std::mutex gTestStateMutex;
769*6467f958SSadaf Ebrahimi 
test_function_runner(test_harness_state * state)770*6467f958SSadaf Ebrahimi void test_function_runner(test_harness_state *state)
771*6467f958SSadaf Ebrahimi {
772*6467f958SSadaf Ebrahimi     int testID;
773*6467f958SSadaf Ebrahimi     test_definition test;
774*6467f958SSadaf Ebrahimi     while (true)
775*6467f958SSadaf Ebrahimi     {
776*6467f958SSadaf Ebrahimi         // Attempt to get a test
777*6467f958SSadaf Ebrahimi         {
778*6467f958SSadaf Ebrahimi             std::lock_guard<std::mutex> lock(gTestStateMutex);
779*6467f958SSadaf Ebrahimi 
780*6467f958SSadaf Ebrahimi             // The queue is empty, we're done
781*6467f958SSadaf Ebrahimi             if (gTestQueue.size() == 0)
782*6467f958SSadaf Ebrahimi             {
783*6467f958SSadaf Ebrahimi                 return;
784*6467f958SSadaf Ebrahimi             }
785*6467f958SSadaf Ebrahimi 
786*6467f958SSadaf Ebrahimi             // Get the test at the front of the queue
787*6467f958SSadaf Ebrahimi             testID = gTestQueue.front();
788*6467f958SSadaf Ebrahimi             gTestQueue.pop_front();
789*6467f958SSadaf Ebrahimi             test = state->tests[testID];
790*6467f958SSadaf Ebrahimi         }
791*6467f958SSadaf Ebrahimi 
792*6467f958SSadaf Ebrahimi         // Execute test
793*6467f958SSadaf Ebrahimi         auto status =
794*6467f958SSadaf Ebrahimi             callSingleTestFunction(test, state->device, state->config);
795*6467f958SSadaf Ebrahimi 
796*6467f958SSadaf Ebrahimi         // Store result
797*6467f958SSadaf Ebrahimi         {
798*6467f958SSadaf Ebrahimi             std::lock_guard<std::mutex> lock(gTestStateMutex);
799*6467f958SSadaf Ebrahimi             state->results[testID] = status;
800*6467f958SSadaf Ebrahimi         }
801*6467f958SSadaf Ebrahimi     }
802*6467f958SSadaf Ebrahimi }
803*6467f958SSadaf Ebrahimi 
callTestFunctions(test_definition testList[],unsigned char selectedTestList[],test_status resultTestList[],int testNum,cl_device_id deviceToUse,const test_harness_config & config)804*6467f958SSadaf Ebrahimi void callTestFunctions(test_definition testList[],
805*6467f958SSadaf Ebrahimi                        unsigned char selectedTestList[],
806*6467f958SSadaf Ebrahimi                        test_status resultTestList[], int testNum,
807*6467f958SSadaf Ebrahimi                        cl_device_id deviceToUse,
808*6467f958SSadaf Ebrahimi                        const test_harness_config &config)
809*6467f958SSadaf Ebrahimi {
810*6467f958SSadaf Ebrahimi     // Execute tests serially
811*6467f958SSadaf Ebrahimi     if (config.numWorkerThreads == 0)
812*6467f958SSadaf Ebrahimi     {
813*6467f958SSadaf Ebrahimi         for (int i = 0; i < testNum; ++i)
814*6467f958SSadaf Ebrahimi         {
815*6467f958SSadaf Ebrahimi             if (selectedTestList[i])
816*6467f958SSadaf Ebrahimi             {
817*6467f958SSadaf Ebrahimi                 resultTestList[i] =
818*6467f958SSadaf Ebrahimi                     callSingleTestFunction(testList[i], deviceToUse, config);
819*6467f958SSadaf Ebrahimi             }
820*6467f958SSadaf Ebrahimi         }
821*6467f958SSadaf Ebrahimi         // Execute tests in parallel with the specified number of worker threads
822*6467f958SSadaf Ebrahimi     }
823*6467f958SSadaf Ebrahimi     else
824*6467f958SSadaf Ebrahimi     {
825*6467f958SSadaf Ebrahimi         // Queue all tests that need to run
826*6467f958SSadaf Ebrahimi         for (int i = 0; i < testNum; ++i)
827*6467f958SSadaf Ebrahimi         {
828*6467f958SSadaf Ebrahimi             if (selectedTestList[i])
829*6467f958SSadaf Ebrahimi             {
830*6467f958SSadaf Ebrahimi                 gTestQueue.push_back(i);
831*6467f958SSadaf Ebrahimi             }
832*6467f958SSadaf Ebrahimi         }
833*6467f958SSadaf Ebrahimi 
834*6467f958SSadaf Ebrahimi         // Spawn thread pool
835*6467f958SSadaf Ebrahimi         std::vector<std::thread *> threads;
836*6467f958SSadaf Ebrahimi         test_harness_state state = { testList, resultTestList, deviceToUse,
837*6467f958SSadaf Ebrahimi                                      config };
838*6467f958SSadaf Ebrahimi         for (unsigned i = 0; i < config.numWorkerThreads; i++)
839*6467f958SSadaf Ebrahimi         {
840*6467f958SSadaf Ebrahimi             log_info("Spawning worker thread %u\n", i);
841*6467f958SSadaf Ebrahimi             threads.push_back(new std::thread(test_function_runner, &state));
842*6467f958SSadaf Ebrahimi         }
843*6467f958SSadaf Ebrahimi 
844*6467f958SSadaf Ebrahimi         // Wait for all threads to complete
845*6467f958SSadaf Ebrahimi         for (auto th : threads)
846*6467f958SSadaf Ebrahimi         {
847*6467f958SSadaf Ebrahimi             th->join();
848*6467f958SSadaf Ebrahimi         }
849*6467f958SSadaf Ebrahimi         assert(gTestQueue.size() == 0);
850*6467f958SSadaf Ebrahimi     }
851*6467f958SSadaf Ebrahimi }
852*6467f958SSadaf Ebrahimi 
notify_callback(const char * errinfo,const void * private_info,size_t cb,void * user_data)853*6467f958SSadaf Ebrahimi void CL_CALLBACK notify_callback(const char *errinfo, const void *private_info,
854*6467f958SSadaf Ebrahimi                                  size_t cb, void *user_data)
855*6467f958SSadaf Ebrahimi {
856*6467f958SSadaf Ebrahimi     log_info("%s\n", errinfo);
857*6467f958SSadaf Ebrahimi }
858*6467f958SSadaf Ebrahimi 
859*6467f958SSadaf Ebrahimi // Actual function execution
callSingleTestFunction(test_definition test,cl_device_id deviceToUse,const test_harness_config & config)860*6467f958SSadaf Ebrahimi test_status callSingleTestFunction(test_definition test,
861*6467f958SSadaf Ebrahimi                                    cl_device_id deviceToUse,
862*6467f958SSadaf Ebrahimi                                    const test_harness_config &config)
863*6467f958SSadaf Ebrahimi {
864*6467f958SSadaf Ebrahimi     test_status status;
865*6467f958SSadaf Ebrahimi     cl_int error;
866*6467f958SSadaf Ebrahimi     cl_context context = NULL;
867*6467f958SSadaf Ebrahimi     cl_command_queue queue = NULL;
868*6467f958SSadaf Ebrahimi 
869*6467f958SSadaf Ebrahimi     log_info("%s...\n", test.name);
870*6467f958SSadaf Ebrahimi     fflush(stdout);
871*6467f958SSadaf Ebrahimi 
872*6467f958SSadaf Ebrahimi     const Version device_version = get_device_cl_version(deviceToUse);
873*6467f958SSadaf Ebrahimi     if (test.min_version > device_version)
874*6467f958SSadaf Ebrahimi     {
875*6467f958SSadaf Ebrahimi         version_expected_info(test.name, "OpenCL",
876*6467f958SSadaf Ebrahimi                               test.min_version.to_string().c_str(),
877*6467f958SSadaf Ebrahimi                               device_version.to_string().c_str());
878*6467f958SSadaf Ebrahimi         return TEST_SKIP;
879*6467f958SSadaf Ebrahimi     }
880*6467f958SSadaf Ebrahimi 
881*6467f958SSadaf Ebrahimi     if (!check_functions_for_offline_compiler(test.name))
882*6467f958SSadaf Ebrahimi     {
883*6467f958SSadaf Ebrahimi         log_info("Subtest %s tests is not supported in offline compiler "
884*6467f958SSadaf Ebrahimi                  "execution path!\n",
885*6467f958SSadaf Ebrahimi                  test.name);
886*6467f958SSadaf Ebrahimi         return TEST_SKIP;
887*6467f958SSadaf Ebrahimi     }
888*6467f958SSadaf Ebrahimi 
889*6467f958SSadaf Ebrahimi     /* Create a context to work with, unless we're told not to */
890*6467f958SSadaf Ebrahimi     if (!config.forceNoContextCreation)
891*6467f958SSadaf Ebrahimi     {
892*6467f958SSadaf Ebrahimi         context = clCreateContext(NULL, 1, &deviceToUse, notify_callback, NULL,
893*6467f958SSadaf Ebrahimi                                   &error);
894*6467f958SSadaf Ebrahimi         if (!context)
895*6467f958SSadaf Ebrahimi         {
896*6467f958SSadaf Ebrahimi             print_error(error, "Unable to create testing context");
897*6467f958SSadaf Ebrahimi             gFailCount++;
898*6467f958SSadaf Ebrahimi             gTestsFailed++;
899*6467f958SSadaf Ebrahimi             return TEST_FAIL;
900*6467f958SSadaf Ebrahimi         }
901*6467f958SSadaf Ebrahimi 
902*6467f958SSadaf Ebrahimi         if (device_version < Version(2, 0))
903*6467f958SSadaf Ebrahimi         {
904*6467f958SSadaf Ebrahimi             queue = clCreateCommandQueue(context, deviceToUse,
905*6467f958SSadaf Ebrahimi                                          config.queueProps, &error);
906*6467f958SSadaf Ebrahimi         }
907*6467f958SSadaf Ebrahimi         else
908*6467f958SSadaf Ebrahimi         {
909*6467f958SSadaf Ebrahimi             const cl_command_queue_properties cmd_queueProps =
910*6467f958SSadaf Ebrahimi                 (config.queueProps) ? CL_QUEUE_PROPERTIES : 0;
911*6467f958SSadaf Ebrahimi             cl_command_queue_properties queueCreateProps[] = {
912*6467f958SSadaf Ebrahimi                 cmd_queueProps, config.queueProps, 0
913*6467f958SSadaf Ebrahimi             };
914*6467f958SSadaf Ebrahimi             queue = clCreateCommandQueueWithProperties(
915*6467f958SSadaf Ebrahimi                 context, deviceToUse, &queueCreateProps[0], &error);
916*6467f958SSadaf Ebrahimi         }
917*6467f958SSadaf Ebrahimi 
918*6467f958SSadaf Ebrahimi         if (queue == NULL)
919*6467f958SSadaf Ebrahimi         {
920*6467f958SSadaf Ebrahimi             print_error(error, "Unable to create testing command queue");
921*6467f958SSadaf Ebrahimi             clReleaseContext(context);
922*6467f958SSadaf Ebrahimi             gFailCount++;
923*6467f958SSadaf Ebrahimi             gTestsFailed++;
924*6467f958SSadaf Ebrahimi             return TEST_FAIL;
925*6467f958SSadaf Ebrahimi         }
926*6467f958SSadaf Ebrahimi     }
927*6467f958SSadaf Ebrahimi 
928*6467f958SSadaf Ebrahimi     /* Run the test and print the result */
929*6467f958SSadaf Ebrahimi     if (test.func == NULL)
930*6467f958SSadaf Ebrahimi     {
931*6467f958SSadaf Ebrahimi         // Skip unimplemented test, can happen when all of the tests are
932*6467f958SSadaf Ebrahimi         // selected
933*6467f958SSadaf Ebrahimi         log_info("%s test currently not implemented\n", test.name);
934*6467f958SSadaf Ebrahimi         status = TEST_SKIP;
935*6467f958SSadaf Ebrahimi     }
936*6467f958SSadaf Ebrahimi     else
937*6467f958SSadaf Ebrahimi     {
938*6467f958SSadaf Ebrahimi         int ret =
939*6467f958SSadaf Ebrahimi             test.func(deviceToUse, context, queue, config.numElementsToUse);
940*6467f958SSadaf Ebrahimi         if (ret == TEST_SKIPPED_ITSELF)
941*6467f958SSadaf Ebrahimi         {
942*6467f958SSadaf Ebrahimi             /* Tests can also let us know they're not supported by the
943*6467f958SSadaf Ebrahimi              * implementation */
944*6467f958SSadaf Ebrahimi             log_info("%s test not supported\n", test.name);
945*6467f958SSadaf Ebrahimi             status = TEST_SKIP;
946*6467f958SSadaf Ebrahimi         }
947*6467f958SSadaf Ebrahimi         else
948*6467f958SSadaf Ebrahimi         {
949*6467f958SSadaf Ebrahimi             /* Print result */
950*6467f958SSadaf Ebrahimi             if (ret == 0)
951*6467f958SSadaf Ebrahimi             {
952*6467f958SSadaf Ebrahimi                 log_info("%s passed\n", test.name);
953*6467f958SSadaf Ebrahimi                 gTestsPassed++;
954*6467f958SSadaf Ebrahimi                 status = TEST_PASS;
955*6467f958SSadaf Ebrahimi             }
956*6467f958SSadaf Ebrahimi             else
957*6467f958SSadaf Ebrahimi             {
958*6467f958SSadaf Ebrahimi                 log_error("%s FAILED\n", test.name);
959*6467f958SSadaf Ebrahimi                 gTestsFailed++;
960*6467f958SSadaf Ebrahimi                 status = TEST_FAIL;
961*6467f958SSadaf Ebrahimi             }
962*6467f958SSadaf Ebrahimi         }
963*6467f958SSadaf Ebrahimi     }
964*6467f958SSadaf Ebrahimi 
965*6467f958SSadaf Ebrahimi     /* Release the context */
966*6467f958SSadaf Ebrahimi     if (!config.forceNoContextCreation)
967*6467f958SSadaf Ebrahimi     {
968*6467f958SSadaf Ebrahimi         int error = clFinish(queue);
969*6467f958SSadaf Ebrahimi         if (error)
970*6467f958SSadaf Ebrahimi         {
971*6467f958SSadaf Ebrahimi             log_error("clFinish failed: %s\n", IGetErrorString(error));
972*6467f958SSadaf Ebrahimi             gFailCount++;
973*6467f958SSadaf Ebrahimi             gTestsFailed++;
974*6467f958SSadaf Ebrahimi             status = TEST_FAIL;
975*6467f958SSadaf Ebrahimi         }
976*6467f958SSadaf Ebrahimi         clReleaseCommandQueue(queue);
977*6467f958SSadaf Ebrahimi         clReleaseContext(context);
978*6467f958SSadaf Ebrahimi     }
979*6467f958SSadaf Ebrahimi 
980*6467f958SSadaf Ebrahimi     return status;
981*6467f958SSadaf Ebrahimi }
982*6467f958SSadaf Ebrahimi 
983*6467f958SSadaf Ebrahimi #if !defined(__APPLE__)
memset_pattern4(void * dest,const void * src_pattern,size_t bytes)984*6467f958SSadaf Ebrahimi void memset_pattern4(void *dest, const void *src_pattern, size_t bytes)
985*6467f958SSadaf Ebrahimi {
986*6467f958SSadaf Ebrahimi     uint32_t pat = ((uint32_t *)src_pattern)[0];
987*6467f958SSadaf Ebrahimi     size_t count = bytes / 4;
988*6467f958SSadaf Ebrahimi     size_t i;
989*6467f958SSadaf Ebrahimi     uint32_t *d = (uint32_t *)dest;
990*6467f958SSadaf Ebrahimi 
991*6467f958SSadaf Ebrahimi     for (i = 0; i < count; i++) d[i] = pat;
992*6467f958SSadaf Ebrahimi 
993*6467f958SSadaf Ebrahimi     d += i;
994*6467f958SSadaf Ebrahimi 
995*6467f958SSadaf Ebrahimi     bytes &= 3;
996*6467f958SSadaf Ebrahimi     if (bytes) memcpy(d, src_pattern, bytes);
997*6467f958SSadaf Ebrahimi }
998*6467f958SSadaf Ebrahimi #endif
999*6467f958SSadaf Ebrahimi 
GetDeviceType(cl_device_id d)1000*6467f958SSadaf Ebrahimi cl_device_type GetDeviceType(cl_device_id d)
1001*6467f958SSadaf Ebrahimi {
1002*6467f958SSadaf Ebrahimi     cl_device_type result = -1;
1003*6467f958SSadaf Ebrahimi     cl_int err =
1004*6467f958SSadaf Ebrahimi         clGetDeviceInfo(d, CL_DEVICE_TYPE, sizeof(result), &result, NULL);
1005*6467f958SSadaf Ebrahimi     if (CL_SUCCESS != err)
1006*6467f958SSadaf Ebrahimi         log_error("ERROR: Unable to get device type for device %p\n", d);
1007*6467f958SSadaf Ebrahimi     return result;
1008*6467f958SSadaf Ebrahimi }
1009*6467f958SSadaf Ebrahimi 
1010*6467f958SSadaf Ebrahimi 
GetOpposingDevice(cl_device_id device)1011*6467f958SSadaf Ebrahimi cl_device_id GetOpposingDevice(cl_device_id device)
1012*6467f958SSadaf Ebrahimi {
1013*6467f958SSadaf Ebrahimi     cl_int error;
1014*6467f958SSadaf Ebrahimi     cl_device_id *otherDevices;
1015*6467f958SSadaf Ebrahimi     cl_uint actualCount;
1016*6467f958SSadaf Ebrahimi     cl_platform_id plat;
1017*6467f958SSadaf Ebrahimi 
1018*6467f958SSadaf Ebrahimi     // Get the platform of the device to use for getting a list of devices
1019*6467f958SSadaf Ebrahimi     error =
1020*6467f958SSadaf Ebrahimi         clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(plat), &plat, NULL);
1021*6467f958SSadaf Ebrahimi     if (error != CL_SUCCESS)
1022*6467f958SSadaf Ebrahimi     {
1023*6467f958SSadaf Ebrahimi         print_error(error, "Unable to get device's platform");
1024*6467f958SSadaf Ebrahimi         return NULL;
1025*6467f958SSadaf Ebrahimi     }
1026*6467f958SSadaf Ebrahimi 
1027*6467f958SSadaf Ebrahimi     // Get a list of all devices
1028*6467f958SSadaf Ebrahimi     error = clGetDeviceIDs(plat, CL_DEVICE_TYPE_ALL, 0, NULL, &actualCount);
1029*6467f958SSadaf Ebrahimi     if (error != CL_SUCCESS)
1030*6467f958SSadaf Ebrahimi     {
1031*6467f958SSadaf Ebrahimi         print_error(error, "Unable to get list of devices size");
1032*6467f958SSadaf Ebrahimi         return NULL;
1033*6467f958SSadaf Ebrahimi     }
1034*6467f958SSadaf Ebrahimi     otherDevices = (cl_device_id *)malloc(actualCount * sizeof(cl_device_id));
1035*6467f958SSadaf Ebrahimi     if (NULL == otherDevices)
1036*6467f958SSadaf Ebrahimi     {
1037*6467f958SSadaf Ebrahimi         print_error(error, "Unable to allocate list of other devices.");
1038*6467f958SSadaf Ebrahimi         return NULL;
1039*6467f958SSadaf Ebrahimi     }
1040*6467f958SSadaf Ebrahimi     BufferOwningPtr<cl_device_id> otherDevicesBuf(otherDevices);
1041*6467f958SSadaf Ebrahimi 
1042*6467f958SSadaf Ebrahimi     error = clGetDeviceIDs(plat, CL_DEVICE_TYPE_ALL, actualCount, otherDevices,
1043*6467f958SSadaf Ebrahimi                            NULL);
1044*6467f958SSadaf Ebrahimi     if (error != CL_SUCCESS)
1045*6467f958SSadaf Ebrahimi     {
1046*6467f958SSadaf Ebrahimi         print_error(error, "Unable to get list of devices");
1047*6467f958SSadaf Ebrahimi         return NULL;
1048*6467f958SSadaf Ebrahimi     }
1049*6467f958SSadaf Ebrahimi 
1050*6467f958SSadaf Ebrahimi     if (actualCount == 1)
1051*6467f958SSadaf Ebrahimi     {
1052*6467f958SSadaf Ebrahimi         return device; // NULL means error, returning self means we couldn't
1053*6467f958SSadaf Ebrahimi                        // find another one
1054*6467f958SSadaf Ebrahimi     }
1055*6467f958SSadaf Ebrahimi 
1056*6467f958SSadaf Ebrahimi     // Loop and just find one that isn't the one we were given
1057*6467f958SSadaf Ebrahimi     cl_uint i;
1058*6467f958SSadaf Ebrahimi     for (i = 0; i < actualCount; i++)
1059*6467f958SSadaf Ebrahimi     {
1060*6467f958SSadaf Ebrahimi         if (otherDevices[i] != device)
1061*6467f958SSadaf Ebrahimi         {
1062*6467f958SSadaf Ebrahimi             cl_device_type newType;
1063*6467f958SSadaf Ebrahimi             error = clGetDeviceInfo(otherDevices[i], CL_DEVICE_TYPE,
1064*6467f958SSadaf Ebrahimi                                     sizeof(newType), &newType, NULL);
1065*6467f958SSadaf Ebrahimi             if (error != CL_SUCCESS)
1066*6467f958SSadaf Ebrahimi             {
1067*6467f958SSadaf Ebrahimi                 print_error(error,
1068*6467f958SSadaf Ebrahimi                             "Unable to get device type for other device");
1069*6467f958SSadaf Ebrahimi                 return NULL;
1070*6467f958SSadaf Ebrahimi             }
1071*6467f958SSadaf Ebrahimi             cl_device_id result = otherDevices[i];
1072*6467f958SSadaf Ebrahimi             return result;
1073*6467f958SSadaf Ebrahimi         }
1074*6467f958SSadaf Ebrahimi     }
1075*6467f958SSadaf Ebrahimi 
1076*6467f958SSadaf Ebrahimi     // Should never get here
1077*6467f958SSadaf Ebrahimi     return NULL;
1078*6467f958SSadaf Ebrahimi }
1079*6467f958SSadaf Ebrahimi 
get_device_cl_version(cl_device_id device)1080*6467f958SSadaf Ebrahimi Version get_device_cl_version(cl_device_id device)
1081*6467f958SSadaf Ebrahimi {
1082*6467f958SSadaf Ebrahimi     size_t str_size;
1083*6467f958SSadaf Ebrahimi     cl_int err = clGetDeviceInfo(device, CL_DEVICE_VERSION, 0, NULL, &str_size);
1084*6467f958SSadaf Ebrahimi     ASSERT_SUCCESS(err, "clGetDeviceInfo");
1085*6467f958SSadaf Ebrahimi 
1086*6467f958SSadaf Ebrahimi     std::vector<char> str(str_size);
1087*6467f958SSadaf Ebrahimi     err =
1088*6467f958SSadaf Ebrahimi         clGetDeviceInfo(device, CL_DEVICE_VERSION, str_size, str.data(), NULL);
1089*6467f958SSadaf Ebrahimi     ASSERT_SUCCESS(err, "clGetDeviceInfo");
1090*6467f958SSadaf Ebrahimi 
1091*6467f958SSadaf Ebrahimi     if (strstr(str.data(), "OpenCL 1.0") != NULL)
1092*6467f958SSadaf Ebrahimi         return Version(1, 0);
1093*6467f958SSadaf Ebrahimi     else if (strstr(str.data(), "OpenCL 1.1") != NULL)
1094*6467f958SSadaf Ebrahimi         return Version(1, 1);
1095*6467f958SSadaf Ebrahimi     else if (strstr(str.data(), "OpenCL 1.2") != NULL)
1096*6467f958SSadaf Ebrahimi         return Version(1, 2);
1097*6467f958SSadaf Ebrahimi     else if (strstr(str.data(), "OpenCL 2.0") != NULL)
1098*6467f958SSadaf Ebrahimi         return Version(2, 0);
1099*6467f958SSadaf Ebrahimi     else if (strstr(str.data(), "OpenCL 2.1") != NULL)
1100*6467f958SSadaf Ebrahimi         return Version(2, 1);
1101*6467f958SSadaf Ebrahimi     else if (strstr(str.data(), "OpenCL 2.2") != NULL)
1102*6467f958SSadaf Ebrahimi         return Version(2, 2);
1103*6467f958SSadaf Ebrahimi     else if (strstr(str.data(), "OpenCL 3.0") != NULL)
1104*6467f958SSadaf Ebrahimi         return Version(3, 0);
1105*6467f958SSadaf Ebrahimi 
1106*6467f958SSadaf Ebrahimi     throw std::runtime_error(std::string("Unknown OpenCL version: ")
1107*6467f958SSadaf Ebrahimi                              + str.data());
1108*6467f958SSadaf Ebrahimi }
1109*6467f958SSadaf Ebrahimi 
check_device_spirv_version_reported(cl_device_id device)1110*6467f958SSadaf Ebrahimi bool check_device_spirv_version_reported(cl_device_id device)
1111*6467f958SSadaf Ebrahimi {
1112*6467f958SSadaf Ebrahimi     size_t str_size;
1113*6467f958SSadaf Ebrahimi     cl_int err;
1114*6467f958SSadaf Ebrahimi     std::vector<char> str;
1115*6467f958SSadaf Ebrahimi     if (gCoreILProgram)
1116*6467f958SSadaf Ebrahimi     {
1117*6467f958SSadaf Ebrahimi         err = clGetDeviceInfo(device, CL_DEVICE_IL_VERSION, 0, NULL, &str_size);
1118*6467f958SSadaf Ebrahimi         if (err != CL_SUCCESS)
1119*6467f958SSadaf Ebrahimi         {
1120*6467f958SSadaf Ebrahimi             log_error(
1121*6467f958SSadaf Ebrahimi                 "clGetDeviceInfo: cannot read CL_DEVICE_IL_VERSION size;");
1122*6467f958SSadaf Ebrahimi             return false;
1123*6467f958SSadaf Ebrahimi         }
1124*6467f958SSadaf Ebrahimi 
1125*6467f958SSadaf Ebrahimi         str.resize(str_size);
1126*6467f958SSadaf Ebrahimi         err = clGetDeviceInfo(device, CL_DEVICE_IL_VERSION, str_size,
1127*6467f958SSadaf Ebrahimi                               str.data(), NULL);
1128*6467f958SSadaf Ebrahimi         if (err != CL_SUCCESS)
1129*6467f958SSadaf Ebrahimi         {
1130*6467f958SSadaf Ebrahimi             log_error(
1131*6467f958SSadaf Ebrahimi                 "clGetDeviceInfo: cannot read CL_DEVICE_IL_VERSION value;");
1132*6467f958SSadaf Ebrahimi             return false;
1133*6467f958SSadaf Ebrahimi         }
1134*6467f958SSadaf Ebrahimi     }
1135*6467f958SSadaf Ebrahimi     else
1136*6467f958SSadaf Ebrahimi     {
1137*6467f958SSadaf Ebrahimi         cl_int err = clGetDeviceInfo(device, CL_DEVICE_IL_VERSION_KHR, 0, NULL,
1138*6467f958SSadaf Ebrahimi                                      &str_size);
1139*6467f958SSadaf Ebrahimi         if (err != CL_SUCCESS)
1140*6467f958SSadaf Ebrahimi         {
1141*6467f958SSadaf Ebrahimi             log_error(
1142*6467f958SSadaf Ebrahimi                 "clGetDeviceInfo: cannot read CL_DEVICE_IL_VERSION_KHR size;");
1143*6467f958SSadaf Ebrahimi             return false;
1144*6467f958SSadaf Ebrahimi         }
1145*6467f958SSadaf Ebrahimi 
1146*6467f958SSadaf Ebrahimi         str.resize(str_size);
1147*6467f958SSadaf Ebrahimi         err = clGetDeviceInfo(device, CL_DEVICE_IL_VERSION_KHR, str_size,
1148*6467f958SSadaf Ebrahimi                               str.data(), NULL);
1149*6467f958SSadaf Ebrahimi         if (err != CL_SUCCESS)
1150*6467f958SSadaf Ebrahimi         {
1151*6467f958SSadaf Ebrahimi             log_error(
1152*6467f958SSadaf Ebrahimi                 "clGetDeviceInfo: cannot read CL_DEVICE_IL_VERSION_KHR value;");
1153*6467f958SSadaf Ebrahimi             return false;
1154*6467f958SSadaf Ebrahimi         }
1155*6467f958SSadaf Ebrahimi     }
1156*6467f958SSadaf Ebrahimi 
1157*6467f958SSadaf Ebrahimi     if (strstr(str.data(), "SPIR-V") == NULL)
1158*6467f958SSadaf Ebrahimi     {
1159*6467f958SSadaf Ebrahimi         log_info("This device does not support SPIR-V offline compilation.\n");
1160*6467f958SSadaf Ebrahimi         return false;
1161*6467f958SSadaf Ebrahimi     }
1162*6467f958SSadaf Ebrahimi     else
1163*6467f958SSadaf Ebrahimi     {
1164*6467f958SSadaf Ebrahimi         Version spirv_version = get_device_spirv_il_version(device);
1165*6467f958SSadaf Ebrahimi         log_info("This device supports SPIR-V offline compilation. SPIR-V "
1166*6467f958SSadaf Ebrahimi                  "version is %s\n",
1167*6467f958SSadaf Ebrahimi                  spirv_version.to_string().c_str());
1168*6467f958SSadaf Ebrahimi     }
1169*6467f958SSadaf Ebrahimi     return true;
1170*6467f958SSadaf Ebrahimi }
1171*6467f958SSadaf Ebrahimi 
get_device_spirv_il_version(cl_device_id device)1172*6467f958SSadaf Ebrahimi Version get_device_spirv_il_version(cl_device_id device)
1173*6467f958SSadaf Ebrahimi {
1174*6467f958SSadaf Ebrahimi     size_t str_size;
1175*6467f958SSadaf Ebrahimi     cl_int err;
1176*6467f958SSadaf Ebrahimi     std::vector<char> str;
1177*6467f958SSadaf Ebrahimi     if (gCoreILProgram)
1178*6467f958SSadaf Ebrahimi     {
1179*6467f958SSadaf Ebrahimi         err = clGetDeviceInfo(device, CL_DEVICE_IL_VERSION, 0, NULL, &str_size);
1180*6467f958SSadaf Ebrahimi         ASSERT_SUCCESS(err, "clGetDeviceInfo");
1181*6467f958SSadaf Ebrahimi 
1182*6467f958SSadaf Ebrahimi         str.resize(str_size);
1183*6467f958SSadaf Ebrahimi         err = clGetDeviceInfo(device, CL_DEVICE_IL_VERSION, str_size,
1184*6467f958SSadaf Ebrahimi                               str.data(), NULL);
1185*6467f958SSadaf Ebrahimi         ASSERT_SUCCESS(err, "clGetDeviceInfo");
1186*6467f958SSadaf Ebrahimi     }
1187*6467f958SSadaf Ebrahimi     else
1188*6467f958SSadaf Ebrahimi     {
1189*6467f958SSadaf Ebrahimi         err = clGetDeviceInfo(device, CL_DEVICE_IL_VERSION_KHR, 0, NULL,
1190*6467f958SSadaf Ebrahimi                               &str_size);
1191*6467f958SSadaf Ebrahimi         ASSERT_SUCCESS(err, "clGetDeviceInfo");
1192*6467f958SSadaf Ebrahimi 
1193*6467f958SSadaf Ebrahimi         str.resize(str_size);
1194*6467f958SSadaf Ebrahimi         err = clGetDeviceInfo(device, CL_DEVICE_IL_VERSION_KHR, str_size,
1195*6467f958SSadaf Ebrahimi                               str.data(), NULL);
1196*6467f958SSadaf Ebrahimi         ASSERT_SUCCESS(err, "clGetDeviceInfo");
1197*6467f958SSadaf Ebrahimi     }
1198*6467f958SSadaf Ebrahimi 
1199*6467f958SSadaf Ebrahimi     if (strstr(str.data(), "SPIR-V_1.0") != NULL)
1200*6467f958SSadaf Ebrahimi         return Version(1, 0);
1201*6467f958SSadaf Ebrahimi     else if (strstr(str.data(), "SPIR-V_1.1") != NULL)
1202*6467f958SSadaf Ebrahimi         return Version(1, 1);
1203*6467f958SSadaf Ebrahimi     else if (strstr(str.data(), "SPIR-V_1.2") != NULL)
1204*6467f958SSadaf Ebrahimi         return Version(1, 2);
1205*6467f958SSadaf Ebrahimi     else if (strstr(str.data(), "SPIR-V_1.3") != NULL)
1206*6467f958SSadaf Ebrahimi         return Version(1, 3);
1207*6467f958SSadaf Ebrahimi     else if (strstr(str.data(), "SPIR-V_1.4") != NULL)
1208*6467f958SSadaf Ebrahimi         return Version(1, 4);
1209*6467f958SSadaf Ebrahimi     else if (strstr(str.data(), "SPIR-V_1.5") != NULL)
1210*6467f958SSadaf Ebrahimi         return Version(1, 5);
1211*6467f958SSadaf Ebrahimi 
1212*6467f958SSadaf Ebrahimi     throw std::runtime_error(std::string("Unknown SPIR-V version: ")
1213*6467f958SSadaf Ebrahimi                              + str.data());
1214*6467f958SSadaf Ebrahimi }
1215*6467f958SSadaf Ebrahimi 
check_spirv_compilation_readiness(cl_device_id device)1216*6467f958SSadaf Ebrahimi test_status check_spirv_compilation_readiness(cl_device_id device)
1217*6467f958SSadaf Ebrahimi {
1218*6467f958SSadaf Ebrahimi     auto ocl_version = get_device_cl_version(device);
1219*6467f958SSadaf Ebrahimi     auto ocl_expected_min_version = Version(2, 1);
1220*6467f958SSadaf Ebrahimi 
1221*6467f958SSadaf Ebrahimi     if (ocl_version < ocl_expected_min_version)
1222*6467f958SSadaf Ebrahimi     {
1223*6467f958SSadaf Ebrahimi         if (is_extension_available(device, "cl_khr_il_program"))
1224*6467f958SSadaf Ebrahimi         {
1225*6467f958SSadaf Ebrahimi             gCoreILProgram = false;
1226*6467f958SSadaf Ebrahimi             bool spirv_supported = check_device_spirv_version_reported(device);
1227*6467f958SSadaf Ebrahimi             if (spirv_supported == false)
1228*6467f958SSadaf Ebrahimi             {
1229*6467f958SSadaf Ebrahimi                 log_error("SPIR-V intermediate language not supported !!! "
1230*6467f958SSadaf Ebrahimi                           "OpenCL %s requires support.\n",
1231*6467f958SSadaf Ebrahimi                           ocl_version.to_string().c_str());
1232*6467f958SSadaf Ebrahimi                 return TEST_FAIL;
1233*6467f958SSadaf Ebrahimi             }
1234*6467f958SSadaf Ebrahimi             else
1235*6467f958SSadaf Ebrahimi             {
1236*6467f958SSadaf Ebrahimi                 return TEST_PASS;
1237*6467f958SSadaf Ebrahimi             }
1238*6467f958SSadaf Ebrahimi         }
1239*6467f958SSadaf Ebrahimi         else
1240*6467f958SSadaf Ebrahimi         {
1241*6467f958SSadaf Ebrahimi             log_error("SPIR-V intermediate language support on OpenCL version "
1242*6467f958SSadaf Ebrahimi                       "%s requires cl_khr_il_program extension.\n",
1243*6467f958SSadaf Ebrahimi                       ocl_version.to_string().c_str());
1244*6467f958SSadaf Ebrahimi             return TEST_SKIP;
1245*6467f958SSadaf Ebrahimi         }
1246*6467f958SSadaf Ebrahimi     }
1247*6467f958SSadaf Ebrahimi 
1248*6467f958SSadaf Ebrahimi     bool spirv_supported = check_device_spirv_version_reported(device);
1249*6467f958SSadaf Ebrahimi     if (ocl_version >= ocl_expected_min_version && ocl_version <= Version(2, 2))
1250*6467f958SSadaf Ebrahimi     {
1251*6467f958SSadaf Ebrahimi         if (spirv_supported == false)
1252*6467f958SSadaf Ebrahimi         {
1253*6467f958SSadaf Ebrahimi             log_error("SPIR-V intermediate language not supported !!! OpenCL "
1254*6467f958SSadaf Ebrahimi                       "%s requires support.\n",
1255*6467f958SSadaf Ebrahimi                       ocl_version.to_string().c_str());
1256*6467f958SSadaf Ebrahimi             return TEST_FAIL;
1257*6467f958SSadaf Ebrahimi         }
1258*6467f958SSadaf Ebrahimi     }
1259*6467f958SSadaf Ebrahimi 
1260*6467f958SSadaf Ebrahimi     if (ocl_version > Version(2, 2))
1261*6467f958SSadaf Ebrahimi     {
1262*6467f958SSadaf Ebrahimi         if (spirv_supported == false)
1263*6467f958SSadaf Ebrahimi         {
1264*6467f958SSadaf Ebrahimi             log_info("SPIR-V intermediate language not supported in OpenCL %s. "
1265*6467f958SSadaf Ebrahimi                      "Test skipped.\n",
1266*6467f958SSadaf Ebrahimi                      ocl_version.to_string().c_str());
1267*6467f958SSadaf Ebrahimi             return TEST_SKIP;
1268*6467f958SSadaf Ebrahimi         }
1269*6467f958SSadaf Ebrahimi     }
1270*6467f958SSadaf Ebrahimi     return TEST_PASS;
1271*6467f958SSadaf Ebrahimi }
1272*6467f958SSadaf Ebrahimi 
getPlatformFromDevice(cl_device_id deviceID)1273*6467f958SSadaf Ebrahimi cl_platform_id getPlatformFromDevice(cl_device_id deviceID)
1274*6467f958SSadaf Ebrahimi {
1275*6467f958SSadaf Ebrahimi     cl_platform_id platform = nullptr;
1276*6467f958SSadaf Ebrahimi     cl_int err = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM, sizeof(platform),
1277*6467f958SSadaf Ebrahimi                                  &platform, nullptr);
1278*6467f958SSadaf Ebrahimi     ASSERT_SUCCESS(err, "clGetDeviceInfo");
1279*6467f958SSadaf Ebrahimi     return platform;
1280*6467f958SSadaf Ebrahimi }
1281*6467f958SSadaf Ebrahimi 
PrintArch(void)1282*6467f958SSadaf Ebrahimi void PrintArch(void)
1283*6467f958SSadaf Ebrahimi {
1284*6467f958SSadaf Ebrahimi     vlog("sizeof( void*) = %zu\n", sizeof(void *));
1285*6467f958SSadaf Ebrahimi #if defined(__ppc__)
1286*6467f958SSadaf Ebrahimi     vlog("ARCH:\tppc\n");
1287*6467f958SSadaf Ebrahimi #elif defined(__ppc64__)
1288*6467f958SSadaf Ebrahimi     vlog("ARCH:\tppc64\n");
1289*6467f958SSadaf Ebrahimi #elif defined(__PPC__)
1290*6467f958SSadaf Ebrahimi     vlog("ARCH:\tppc\n");
1291*6467f958SSadaf Ebrahimi #elif defined(__i386__)
1292*6467f958SSadaf Ebrahimi     vlog("ARCH:\ti386\n");
1293*6467f958SSadaf Ebrahimi #elif defined(__x86_64__)
1294*6467f958SSadaf Ebrahimi     vlog("ARCH:\tx86_64\n");
1295*6467f958SSadaf Ebrahimi #elif defined(__arm__)
1296*6467f958SSadaf Ebrahimi     vlog("ARCH:\tarm\n");
1297*6467f958SSadaf Ebrahimi #elif defined(__aarch64__)
1298*6467f958SSadaf Ebrahimi     vlog("ARCH:\taarch64\n");
1299*6467f958SSadaf Ebrahimi #elif defined(_WIN32)
1300*6467f958SSadaf Ebrahimi     vlog("ARCH:\tWindows\n");
1301*6467f958SSadaf Ebrahimi #else
1302*6467f958SSadaf Ebrahimi #error unknown arch
1303*6467f958SSadaf Ebrahimi #endif
1304*6467f958SSadaf Ebrahimi 
1305*6467f958SSadaf Ebrahimi #if defined(__APPLE__)
1306*6467f958SSadaf Ebrahimi 
1307*6467f958SSadaf Ebrahimi     int type = 0;
1308*6467f958SSadaf Ebrahimi     size_t typeSize = sizeof(type);
1309*6467f958SSadaf Ebrahimi     sysctlbyname("hw.cputype", &type, &typeSize, NULL, 0);
1310*6467f958SSadaf Ebrahimi     vlog("cpu type:\t%d\n", type);
1311*6467f958SSadaf Ebrahimi     typeSize = sizeof(type);
1312*6467f958SSadaf Ebrahimi     sysctlbyname("hw.cpusubtype", &type, &typeSize, NULL, 0);
1313*6467f958SSadaf Ebrahimi     vlog("cpu subtype:\t%d\n", type);
1314*6467f958SSadaf Ebrahimi 
1315*6467f958SSadaf Ebrahimi #elif defined(__linux__)
1316*6467f958SSadaf Ebrahimi     struct utsname buffer;
1317*6467f958SSadaf Ebrahimi 
1318*6467f958SSadaf Ebrahimi     if (uname(&buffer) != 0)
1319*6467f958SSadaf Ebrahimi     {
1320*6467f958SSadaf Ebrahimi         vlog("uname error");
1321*6467f958SSadaf Ebrahimi     }
1322*6467f958SSadaf Ebrahimi     else
1323*6467f958SSadaf Ebrahimi     {
1324*6467f958SSadaf Ebrahimi         vlog("system name = %s\n", buffer.sysname);
1325*6467f958SSadaf Ebrahimi         vlog("node name   = %s\n", buffer.nodename);
1326*6467f958SSadaf Ebrahimi         vlog("release     = %s\n", buffer.release);
1327*6467f958SSadaf Ebrahimi         vlog("version     = %s\n", buffer.version);
1328*6467f958SSadaf Ebrahimi         vlog("machine     = %s\n", buffer.machine);
1329*6467f958SSadaf Ebrahimi     }
1330*6467f958SSadaf Ebrahimi #endif
1331*6467f958SSadaf Ebrahimi }
1332