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