1*6467f958SSadaf Ebrahimi //
2*6467f958SSadaf Ebrahimi // Copyright (c) 2017 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 "parseParameters.h"
17*6467f958SSadaf Ebrahimi
18*6467f958SSadaf Ebrahimi #include "errorHelpers.h"
19*6467f958SSadaf Ebrahimi #include "testHarness.h"
20*6467f958SSadaf Ebrahimi #include "ThreadPool.h"
21*6467f958SSadaf Ebrahimi
22*6467f958SSadaf Ebrahimi #include <iostream>
23*6467f958SSadaf Ebrahimi #include <sstream>
24*6467f958SSadaf Ebrahimi #include <sys/types.h>
25*6467f958SSadaf Ebrahimi #include <sys/stat.h>
26*6467f958SSadaf Ebrahimi #include <string.h>
27*6467f958SSadaf Ebrahimi
28*6467f958SSadaf Ebrahimi using namespace std;
29*6467f958SSadaf Ebrahimi
30*6467f958SSadaf Ebrahimi #define DEFAULT_COMPILATION_PROGRAM "cl_offline_compiler"
31*6467f958SSadaf Ebrahimi #define DEFAULT_SPIRV_VALIDATOR "spirv-val"
32*6467f958SSadaf Ebrahimi
33*6467f958SSadaf Ebrahimi CompilationMode gCompilationMode = kOnline;
34*6467f958SSadaf Ebrahimi CompilationCacheMode gCompilationCacheMode = kCacheModeCompileIfAbsent;
35*6467f958SSadaf Ebrahimi std::string gCompilationCachePath = ".";
36*6467f958SSadaf Ebrahimi std::string gCompilationProgram = DEFAULT_COMPILATION_PROGRAM;
37*6467f958SSadaf Ebrahimi bool gDisableSPIRVValidation = false;
38*6467f958SSadaf Ebrahimi std::string gSPIRVValidator = DEFAULT_SPIRV_VALIDATOR;
39*6467f958SSadaf Ebrahimi unsigned gNumWorkerThreads;
40*6467f958SSadaf Ebrahimi
helpInfo()41*6467f958SSadaf Ebrahimi void helpInfo()
42*6467f958SSadaf Ebrahimi {
43*6467f958SSadaf Ebrahimi log_info(
44*6467f958SSadaf Ebrahimi R"(Common options:
45*6467f958SSadaf Ebrahimi -h, --help
46*6467f958SSadaf Ebrahimi This help
47*6467f958SSadaf Ebrahimi --compilation-mode <mode>
48*6467f958SSadaf Ebrahimi Specify a compilation mode. Mode can be:
49*6467f958SSadaf Ebrahimi online Use online compilation (default)
50*6467f958SSadaf Ebrahimi binary Use binary offline compilation
51*6467f958SSadaf Ebrahimi spir-v Use SPIR-V offline compilation
52*6467f958SSadaf Ebrahimi --num-worker-threads <num>
53*6467f958SSadaf Ebrahimi Select parallel execution with the specified number of worker threads.
54*6467f958SSadaf Ebrahimi
55*6467f958SSadaf Ebrahimi For offline compilation (binary and spir-v modes) only:
56*6467f958SSadaf Ebrahimi --compilation-cache-mode <cache-mode>
57*6467f958SSadaf Ebrahimi Specify a compilation caching mode:
58*6467f958SSadaf Ebrahimi compile-if-absent
59*6467f958SSadaf Ebrahimi Read from cache if already populated, or else perform
60*6467f958SSadaf Ebrahimi offline compilation (default)
61*6467f958SSadaf Ebrahimi force-read
62*6467f958SSadaf Ebrahimi Force reading from the cache
63*6467f958SSadaf Ebrahimi overwrite
64*6467f958SSadaf Ebrahimi Disable reading from the cache
65*6467f958SSadaf Ebrahimi dump-cl-files
66*6467f958SSadaf Ebrahimi Dumps the .cl and build .options files used by the test suite
67*6467f958SSadaf Ebrahimi --compilation-cache-path <path>
68*6467f958SSadaf Ebrahimi Path for offline compiler output and CL source
69*6467f958SSadaf Ebrahimi --compilation-program <prog>
70*6467f958SSadaf Ebrahimi Program to use for offline compilation, defaults to:
71*6467f958SSadaf Ebrahimi )" DEFAULT_COMPILATION_PROGRAM R"(
72*6467f958SSadaf Ebrahimi
73*6467f958SSadaf Ebrahimi For spir-v mode only:
74*6467f958SSadaf Ebrahimi --disable-spirv-validation
75*6467f958SSadaf Ebrahimi Disable validation of SPIR-V using the SPIR-V validator
76*6467f958SSadaf Ebrahimi --spirv-validator
77*6467f958SSadaf Ebrahimi Path for SPIR-V validator, defaults to )" DEFAULT_SPIRV_VALIDATOR "\n"
78*6467f958SSadaf Ebrahimi "\n");
79*6467f958SSadaf Ebrahimi }
80*6467f958SSadaf Ebrahimi
parseCustomParam(int argc,const char * argv[],const char * ignore)81*6467f958SSadaf Ebrahimi int parseCustomParam(int argc, const char *argv[], const char *ignore)
82*6467f958SSadaf Ebrahimi {
83*6467f958SSadaf Ebrahimi int delArg = 0;
84*6467f958SSadaf Ebrahimi
85*6467f958SSadaf Ebrahimi for (int i = 1; i < argc; i++)
86*6467f958SSadaf Ebrahimi {
87*6467f958SSadaf Ebrahimi if (ignore != 0)
88*6467f958SSadaf Ebrahimi {
89*6467f958SSadaf Ebrahimi // skip parameters that require special/different treatment in
90*6467f958SSadaf Ebrahimi // application (generic interpretation and parameter removal will
91*6467f958SSadaf Ebrahimi // not be performed)
92*6467f958SSadaf Ebrahimi const char *ptr = strstr(ignore, argv[i]);
93*6467f958SSadaf Ebrahimi if (ptr != 0 && (ptr == ignore || ptr[-1] == ' ')
94*6467f958SSadaf Ebrahimi && // first on list or ' ' before
95*6467f958SSadaf Ebrahimi (ptr[strlen(argv[i])] == 0
96*6467f958SSadaf Ebrahimi || ptr[strlen(argv[i])] == ' ')) // last on list or ' ' after
97*6467f958SSadaf Ebrahimi continue;
98*6467f958SSadaf Ebrahimi }
99*6467f958SSadaf Ebrahimi
100*6467f958SSadaf Ebrahimi delArg = 0;
101*6467f958SSadaf Ebrahimi
102*6467f958SSadaf Ebrahimi if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
103*6467f958SSadaf Ebrahimi {
104*6467f958SSadaf Ebrahimi // Note: we don't increment delArg to delete this argument,
105*6467f958SSadaf Ebrahimi // to allow the caller's argument parsing routine to see the
106*6467f958SSadaf Ebrahimi // option and print its own help.
107*6467f958SSadaf Ebrahimi helpInfo();
108*6467f958SSadaf Ebrahimi }
109*6467f958SSadaf Ebrahimi else if (!strcmp(argv[i], "--compilation-mode"))
110*6467f958SSadaf Ebrahimi {
111*6467f958SSadaf Ebrahimi delArg++;
112*6467f958SSadaf Ebrahimi if ((i + 1) < argc)
113*6467f958SSadaf Ebrahimi {
114*6467f958SSadaf Ebrahimi delArg++;
115*6467f958SSadaf Ebrahimi const char *mode = argv[i + 1];
116*6467f958SSadaf Ebrahimi
117*6467f958SSadaf Ebrahimi if (!strcmp(mode, "online"))
118*6467f958SSadaf Ebrahimi {
119*6467f958SSadaf Ebrahimi gCompilationMode = kOnline;
120*6467f958SSadaf Ebrahimi }
121*6467f958SSadaf Ebrahimi else if (!strcmp(mode, "binary"))
122*6467f958SSadaf Ebrahimi {
123*6467f958SSadaf Ebrahimi gCompilationMode = kBinary;
124*6467f958SSadaf Ebrahimi }
125*6467f958SSadaf Ebrahimi else if (!strcmp(mode, "spir-v"))
126*6467f958SSadaf Ebrahimi {
127*6467f958SSadaf Ebrahimi gCompilationMode = kSpir_v;
128*6467f958SSadaf Ebrahimi }
129*6467f958SSadaf Ebrahimi else
130*6467f958SSadaf Ebrahimi {
131*6467f958SSadaf Ebrahimi log_error("Compilation mode not recognized: %s\n", mode);
132*6467f958SSadaf Ebrahimi return -1;
133*6467f958SSadaf Ebrahimi }
134*6467f958SSadaf Ebrahimi log_info("Compilation mode specified: %s\n", mode);
135*6467f958SSadaf Ebrahimi }
136*6467f958SSadaf Ebrahimi else
137*6467f958SSadaf Ebrahimi {
138*6467f958SSadaf Ebrahimi log_error("Compilation mode parameters are incorrect. Usage:\n"
139*6467f958SSadaf Ebrahimi " --compilation-mode <online|binary|spir-v>\n");
140*6467f958SSadaf Ebrahimi return -1;
141*6467f958SSadaf Ebrahimi }
142*6467f958SSadaf Ebrahimi }
143*6467f958SSadaf Ebrahimi else if (!strcmp(argv[i], "--num-worker-threads"))
144*6467f958SSadaf Ebrahimi {
145*6467f958SSadaf Ebrahimi delArg++;
146*6467f958SSadaf Ebrahimi if ((i + 1) < argc)
147*6467f958SSadaf Ebrahimi {
148*6467f958SSadaf Ebrahimi delArg++;
149*6467f958SSadaf Ebrahimi const char *numthstr = argv[i + 1];
150*6467f958SSadaf Ebrahimi
151*6467f958SSadaf Ebrahimi gNumWorkerThreads = atoi(numthstr);
152*6467f958SSadaf Ebrahimi }
153*6467f958SSadaf Ebrahimi else
154*6467f958SSadaf Ebrahimi {
155*6467f958SSadaf Ebrahimi log_error(
156*6467f958SSadaf Ebrahimi "A parameter to --num-worker-threads must be provided!\n");
157*6467f958SSadaf Ebrahimi return -1;
158*6467f958SSadaf Ebrahimi }
159*6467f958SSadaf Ebrahimi }
160*6467f958SSadaf Ebrahimi else if (!strcmp(argv[i], "--compilation-cache-mode"))
161*6467f958SSadaf Ebrahimi {
162*6467f958SSadaf Ebrahimi delArg++;
163*6467f958SSadaf Ebrahimi if ((i + 1) < argc)
164*6467f958SSadaf Ebrahimi {
165*6467f958SSadaf Ebrahimi delArg++;
166*6467f958SSadaf Ebrahimi const char *mode = argv[i + 1];
167*6467f958SSadaf Ebrahimi
168*6467f958SSadaf Ebrahimi if (!strcmp(mode, "compile-if-absent"))
169*6467f958SSadaf Ebrahimi {
170*6467f958SSadaf Ebrahimi gCompilationCacheMode = kCacheModeCompileIfAbsent;
171*6467f958SSadaf Ebrahimi }
172*6467f958SSadaf Ebrahimi else if (!strcmp(mode, "force-read"))
173*6467f958SSadaf Ebrahimi {
174*6467f958SSadaf Ebrahimi gCompilationCacheMode = kCacheModeForceRead;
175*6467f958SSadaf Ebrahimi }
176*6467f958SSadaf Ebrahimi else if (!strcmp(mode, "overwrite"))
177*6467f958SSadaf Ebrahimi {
178*6467f958SSadaf Ebrahimi gCompilationCacheMode = kCacheModeOverwrite;
179*6467f958SSadaf Ebrahimi }
180*6467f958SSadaf Ebrahimi else if (!strcmp(mode, "dump-cl-files"))
181*6467f958SSadaf Ebrahimi {
182*6467f958SSadaf Ebrahimi gCompilationCacheMode = kCacheModeDumpCl;
183*6467f958SSadaf Ebrahimi }
184*6467f958SSadaf Ebrahimi else
185*6467f958SSadaf Ebrahimi {
186*6467f958SSadaf Ebrahimi log_error("Compilation cache mode not recognized: %s\n",
187*6467f958SSadaf Ebrahimi mode);
188*6467f958SSadaf Ebrahimi return -1;
189*6467f958SSadaf Ebrahimi }
190*6467f958SSadaf Ebrahimi log_info("Compilation cache mode specified: %s\n", mode);
191*6467f958SSadaf Ebrahimi }
192*6467f958SSadaf Ebrahimi else
193*6467f958SSadaf Ebrahimi {
194*6467f958SSadaf Ebrahimi log_error(
195*6467f958SSadaf Ebrahimi "Compilation cache mode parameters are incorrect. Usage:\n"
196*6467f958SSadaf Ebrahimi " --compilation-cache-mode "
197*6467f958SSadaf Ebrahimi "<compile-if-absent|force-read|overwrite>\n");
198*6467f958SSadaf Ebrahimi return -1;
199*6467f958SSadaf Ebrahimi }
200*6467f958SSadaf Ebrahimi }
201*6467f958SSadaf Ebrahimi else if (!strcmp(argv[i], "--compilation-cache-path"))
202*6467f958SSadaf Ebrahimi {
203*6467f958SSadaf Ebrahimi delArg++;
204*6467f958SSadaf Ebrahimi if ((i + 1) < argc)
205*6467f958SSadaf Ebrahimi {
206*6467f958SSadaf Ebrahimi delArg++;
207*6467f958SSadaf Ebrahimi gCompilationCachePath = argv[i + 1];
208*6467f958SSadaf Ebrahimi }
209*6467f958SSadaf Ebrahimi else
210*6467f958SSadaf Ebrahimi {
211*6467f958SSadaf Ebrahimi log_error("Path argument for --compilation-cache-path was not "
212*6467f958SSadaf Ebrahimi "specified.\n");
213*6467f958SSadaf Ebrahimi return -1;
214*6467f958SSadaf Ebrahimi }
215*6467f958SSadaf Ebrahimi }
216*6467f958SSadaf Ebrahimi else if (!strcmp(argv[i], "--compilation-program"))
217*6467f958SSadaf Ebrahimi {
218*6467f958SSadaf Ebrahimi delArg++;
219*6467f958SSadaf Ebrahimi if ((i + 1) < argc)
220*6467f958SSadaf Ebrahimi {
221*6467f958SSadaf Ebrahimi delArg++;
222*6467f958SSadaf Ebrahimi gCompilationProgram = argv[i + 1];
223*6467f958SSadaf Ebrahimi }
224*6467f958SSadaf Ebrahimi else
225*6467f958SSadaf Ebrahimi {
226*6467f958SSadaf Ebrahimi log_error("Program argument for --compilation-program was not "
227*6467f958SSadaf Ebrahimi "specified.\n");
228*6467f958SSadaf Ebrahimi return -1;
229*6467f958SSadaf Ebrahimi }
230*6467f958SSadaf Ebrahimi }
231*6467f958SSadaf Ebrahimi else if (!strcmp(argv[i], "--disable-spirv-validation"))
232*6467f958SSadaf Ebrahimi {
233*6467f958SSadaf Ebrahimi delArg++;
234*6467f958SSadaf Ebrahimi gDisableSPIRVValidation = true;
235*6467f958SSadaf Ebrahimi }
236*6467f958SSadaf Ebrahimi else if (!strcmp(argv[i], "--spirv-validator"))
237*6467f958SSadaf Ebrahimi {
238*6467f958SSadaf Ebrahimi delArg++;
239*6467f958SSadaf Ebrahimi if ((i + 1) < argc)
240*6467f958SSadaf Ebrahimi {
241*6467f958SSadaf Ebrahimi delArg++;
242*6467f958SSadaf Ebrahimi gSPIRVValidator = argv[i + 1];
243*6467f958SSadaf Ebrahimi }
244*6467f958SSadaf Ebrahimi else
245*6467f958SSadaf Ebrahimi {
246*6467f958SSadaf Ebrahimi log_error("Program argument for --spirv-validator was not "
247*6467f958SSadaf Ebrahimi "specified.\n");
248*6467f958SSadaf Ebrahimi return -1;
249*6467f958SSadaf Ebrahimi }
250*6467f958SSadaf Ebrahimi }
251*6467f958SSadaf Ebrahimi
252*6467f958SSadaf Ebrahimi // cleaning parameters from argv tab
253*6467f958SSadaf Ebrahimi for (int j = i; j < argc - delArg; j++) argv[j] = argv[j + delArg];
254*6467f958SSadaf Ebrahimi argc -= delArg;
255*6467f958SSadaf Ebrahimi i -= delArg;
256*6467f958SSadaf Ebrahimi }
257*6467f958SSadaf Ebrahimi
258*6467f958SSadaf Ebrahimi if ((gCompilationCacheMode == kCacheModeForceRead
259*6467f958SSadaf Ebrahimi || gCompilationCacheMode == kCacheModeOverwrite)
260*6467f958SSadaf Ebrahimi && gCompilationMode == kOnline)
261*6467f958SSadaf Ebrahimi {
262*6467f958SSadaf Ebrahimi log_error("Compilation cache mode can only be specified when using an "
263*6467f958SSadaf Ebrahimi "offline compilation mode.\n");
264*6467f958SSadaf Ebrahimi return -1;
265*6467f958SSadaf Ebrahimi }
266*6467f958SSadaf Ebrahimi
267*6467f958SSadaf Ebrahimi return argc;
268*6467f958SSadaf Ebrahimi }
269*6467f958SSadaf Ebrahimi
is_power_of_two(int number)270*6467f958SSadaf Ebrahimi bool is_power_of_two(int number) { return number && !(number & (number - 1)); }
271*6467f958SSadaf Ebrahimi
parseWimpyReductionFactor(const char * & arg,int & wimpyReductionFactor)272*6467f958SSadaf Ebrahimi extern void parseWimpyReductionFactor(const char *&arg,
273*6467f958SSadaf Ebrahimi int &wimpyReductionFactor)
274*6467f958SSadaf Ebrahimi {
275*6467f958SSadaf Ebrahimi const char *arg_temp = strchr(&arg[1], ']');
276*6467f958SSadaf Ebrahimi if (arg_temp != 0)
277*6467f958SSadaf Ebrahimi {
278*6467f958SSadaf Ebrahimi int new_factor = atoi(&arg[1]);
279*6467f958SSadaf Ebrahimi arg = arg_temp; // Advance until ']'
280*6467f958SSadaf Ebrahimi if (is_power_of_two(new_factor))
281*6467f958SSadaf Ebrahimi {
282*6467f958SSadaf Ebrahimi log_info("\n Wimpy reduction factor changed from %d to %d \n",
283*6467f958SSadaf Ebrahimi wimpyReductionFactor, new_factor);
284*6467f958SSadaf Ebrahimi wimpyReductionFactor = new_factor;
285*6467f958SSadaf Ebrahimi }
286*6467f958SSadaf Ebrahimi else
287*6467f958SSadaf Ebrahimi {
288*6467f958SSadaf Ebrahimi log_info("\n WARNING: Incorrect wimpy reduction factor %d, must be "
289*6467f958SSadaf Ebrahimi "power of 2. The default value will be used.\n",
290*6467f958SSadaf Ebrahimi new_factor);
291*6467f958SSadaf Ebrahimi }
292*6467f958SSadaf Ebrahimi }
293*6467f958SSadaf Ebrahimi }
294